leetcode 第133场双周赛 100333.统计逆序对的数目【计数dp/滚动数组/前缀和优化】

在这里插入图片描述
分析:
先考虑如下问题。

求长度为n,逆序对为m的排列数量。

可以考虑dpdp[i][j]定义为长度为i,逆序对为j的排列数量。

dp[1][0] = 1;
//枚举排列长度,或者认为枚举当前需要插到长度为i-1的排列中的数字
for(int i = 1; i <= n; ++i)  
{
    for(int j = 0; j <= i * (i + 1) / 2; ++j)
    {
        //枚举当前数字插到的位置,一共i个位置,分别可能使逆序对增加0~i-1个
        for(int k = 0; k < i; ++k)
        {
            if(j >= k)
            {
                dp[i][j] += dp[i - 1][j - k];
            }
        }
    }
}

在懂了上述dp之后,再来考虑本题。主要有两个问题。

  • 另外考虑,如果dp[i][j]是否依旧可以这样求,因为上述问题中对于长度为i的排列,前i-1个数字确定的,i一定是最大的,我们只需要考虑它放在哪个位置即可。
  • 如何同时满足requirements[i][endi] = cntirequirements[j][endj] = cntj,其中i!=j

对于第一点,肯定是可以这样求的,一方面我们不需要关心前i-1个数字是什么,只需要认为我们枚举的第i个数字是这i个数字中最大的(类似上述思路)或者是最小的(与最大的等效并且更加方便理解上述dp的最内层循环)即可,另一方面我们看到至少有一个i满足endi == n - 1

对于第二点,我们只需要在dp的过程中适当修改。若 ∃ e n d j = = i \exists end_j == i endj==i,则正常求 d p [ i ] [ c n t j ] dp[i][cnt_j] dp[i][cntj]的值,而 d p [ i ] [ k ] = 0 , k ≠ c n t j dp[i][k]=0,k\ne cnt_j dp[i][k]=0,k=cntj

AC代码

class Solution {
public:
    int numberOfPermutations(int n, vector<vector<int>>& requirements) {
        
        const int mod = 1e9 + 7;
        
        vector<int> vt(305, -1);
        for(auto x: requirements) vt[x[0] + 1] = x[1];

        vector<vector<int>> dp(305, vector<int>(405, 0));
        dp[0][0] = 1;

        for (int i = 1; i <= n; ++i) 
        {
            if (vt[i] != -1) 
            {
                int j = vt[i];
                for (int k = 0; k < i; ++k) if (j >= k) dp[i][j] = (dp[i][j] + dp[i - 1][j - k]) % mod;
                continue;
            }
            for (int j = 0; j <= min(400, (1 + i) * i / 2); ++j) 
            {
                for (int k = 0; k < i; ++k) 
                {
                    if (j >= k) dp[i][j] = (dp[i][j] + dp[i - 1][j - k]) % mod;
                }
            }
        }
        
        return dp[n][vt[n]];
    }
};
//dp数组定义为vector,如果定义为数组,一定记得先memset 0
//(dp[i][j] += dp[i - 1][j - k]) % mod不等价于dp[i][j] = (dp[i][j] + dp[i - 1][j - k]) % mod;
//(dp[i][j] += dp[i - 1][j - k]) % mod,模完之后值未赋给任何数。

上述代码已经可以AC,但是可以进一步优化

  • dp[i][j]的递推过程中,只用到了dp[i-1][j-k],故可以通过滚动数组优化空间。
  • 对于最内层枚举k的循环,我们发现递推公式等价于 d p [ i ] [ j ] = ∑ k = j − ( i − 1 ) j d p [ i − 1 ] [ k ] dp[i][j] = \sum_{k=j-(i-1)}^{j} dp[i-1][k] dp[i][j]=k=j(i1)jdp[i1][k],即是dp[i-1]数组的一个前缀和,故可以预处理出前缀和,使得dp[i][j]实现O(1)递推,优化为两层循环。

优化后的代码:

class Solution {
public:
    int numberOfPermutations(int n, vector<vector<int>>& requirements) {
        
        const int mod = 1e9 + 7;
        
        vector<int> vt(305, -1);
        for(auto x: requirements) vt[x[0] + 1] = x[1];

        vector<int> dp(405, 0);
        vector<int> sum(405, 0);
        dp[0] = 1;

        for (int i = 1; i <= n; ++i) 
        {
            sum[0] = dp[0];
            for(int j = 1; j <= min(400, (1 + i) * i / 2); ++j) sum[j] = (sum[j - 1] + dp[j]) % mod;
            if (vt[i] != -1) 
            {
                for(int j = 0; j <= min(400, (1 + i) * i / 2); ++j) dp[j] = 0;
                int j = vt[i];
                if(j < i) dp[j] = sum[j];
                else dp[j] = (sum[j] - sum[j - i] + mod) % mod;
                continue;
            }
            for (int j = 0; j <= min(400, (1 + i) * i / 2); ++j) 
            {
                if(j < i) dp[j] = sum[j];
                else dp[j] = (sum[j] - sum[j - i] + mod) % mod;
            }
        }
        
        return dp[vt[n]];
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/758266.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

笔记本电脑安装CentOS

正文共&#xff1a;1234 字 24 图&#xff0c;预估阅读时间&#xff1a;2 分钟 前面我们对VPP进行了多次介绍&#xff08;羡慕&#xff01;大佬的VPP能达到180G性能&#xff0c;而我的却只有13.5G&#xff09;&#xff0c;可以发现他的很多优点&#xff0c;但是我们也可以发现它…

socket编程常见操作

1、连接的建立 分为两种&#xff1a;服务端处理接收客户端的连接&#xff1b;服务端作为客户端连接第三方服务 //作为服务端 int listenfd socket(AF_INET, SOCK_STREAM, 0); bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr))) listen(listenfd, 10); //…

【单片机毕业设计11-基于stm32c8t6的智能水质检测】

【单片机毕业设计11-基于stm32c8t6的智能水质检测】 前言一、功能介绍二、硬件部分三、软件部分总结 前言 &#x1f525;这里是小殷学长&#xff0c;单片机毕业设计篇11基于stm32的智能水质检测系统 &#x1f9ff;创作不易&#xff0c;拒绝白嫖可私 一、功能介绍 -------------…

武汉星起航:亚马逊欧洲站潮流指南,满足年轻人选品需求

在充满活力的20-30岁年龄段&#xff0c;年轻人们充满朝气&#xff0c;追求时尚与品质&#xff0c;对生活充满无限期待。亚马逊欧洲站作为全球领先的电商平台&#xff0c;为这一年龄段的人群提供了丰富多样的商品选择。武汉星起航将为您介绍亚马逊欧洲站针对20-30岁人群的选品攻…

三元表达式解析器

题意&#xff1a;其实本质上就是三目运算 &#xff0c;只不过跟我们以往的三目运算不同的是&#xff0c;这一系列的运算可以把T 和 F 都参与到运算中。设x5 表达式 x>2?T:F 最终返回T. 思路&#xff1a; 1.从后往前遍历字符数组 2.如果遇到的是 非&#xff1f;和 非&…

C++:静态断言内存对齐

静态断言 C中的断言assert (1)直接参考&#xff1a;https://www.cnblogs.com/lvchaoshun/p/7816288.html (2)C的assert是运行时检测发现错误&#xff0c;而不是编译时 (3)C在编译时错误用#error来输出C静态断言 (1)C引入static_assert(表达式, “提示字符串”)来实现编译时的静…

华为手机改变休眠时间 不让手机动不动黑屏

在手机中找到设置 并打开 在里面找到显示与亮度 并点开 找到并点击休眠操作项 然后就会弹出 多久进入休眠 可以调久一点

LeetCode 1527, 54,114

目录 1527. 患某种疾病的患者题目链接表要求知识点思路代码 54. 螺旋矩阵题目链接标签思路代码 114. 二叉树展开为链表题目链接标签前序遍历思路代码 前驱思路代码 1527. 患某种疾病的患者 题目链接 1527. 患某种疾病的患者 表 表Patients的字段为patient_id、patient_name…

等保测评练习16

等级保护初级测评师试题16 姓名&#xff1a; 成绩&#xff1a; 一、判断题&#xff08;10110分&#xff09; 1.虚拟机被非法利用后&#xff0c;可能被当作跳板机。&#xff08;T&#xff09; P312 2.云服务商&#xff0c;为云计算服务…

初识 Redis

基础知识网上很多&#xff0c;就不写的太啰嗦&#xff0c;这里纪录一下我的首次使用。 一、redis 安装 在服务器上安装 redis 我的服务器环境是宝塔&#xff0c;方便安装 php 扩展打开 redis 二、项目中的实际应用 首先说明&#xff0c;项目环境是 php redis 的一些基本操…

TypeScript学习笔记(全)

文章目录 TypeScript入门2.编译并运行TS代码2.1.简化运行ts步骤 3.TS中的常用类型3.1.TS中的类型注解3.2.TS中的原始类型3.3.TS中的数组类型3.4.TS中的联合类型3.5.类型别名3.6.函数类型3.6.1.单独执行参数、返回值类型3.6.2.同时指定参数&#xff0c;返回值类型3.6.3.函数的vo…

昇思25天学习打卡营第4天|扩散模型

文章目录 昇思MindSpore应用实践基于MindSpore的Diffusion扩散模型1、Diffusion Models 简介2、构建 Diffusion Model 的准备工作3、Attention 机制4、条件 U-Net5、Diffusion 正向过程6、Diffusion 反向过程7、Diffusion 模型训练 Reference 昇思MindSpore应用实践 本系列文章…

掌握Python编程的深层技能

一、Python基础语法、变量、列表、字典等运用 1.运行python程序的两种方式 1.交互式即时得到程序的运行结果 2.脚本方式把程序写到文件里(约定俗称文件名后缀为.py),然后用python解释器解释执行其中的内容2.python程序运行的三个步骤 python3.8 C:\a\b\c.py 1.先启动python3…

什么是产线工控安全,如何保障产线设备的安全

什么是产线工控安全&#xff1f; 工控&#xff0c;指的是工业自动化控制&#xff0c;主要利用电子电气、机械、软件组合实现。即是工业控制系统&#xff0c;或者是工厂自动化控制。产线工控安全指的是工业控制系统的数据、网络和系统安全。随着工业信息化的迅猛发展&#xff0…

【Lua】第一篇:在Linux系统中安装搭建lua5.4.1环境

文章目录 一. 远程下载安装包二. 解压安装包三. 编译安装Lua环境 一. 远程下载安装包 输入以下命令即可在当前目录下&#xff0c;远程下载安装包lua-5.4.1.tar.gz&#xff1a; wget http://www.lua.org/ftp/lua-5.4.1.tar.gzPS&#xff1a;其他版本的安装包如下&#xff0c;可…

鸿蒙项目实战-月木学途:1.编写首页,包括搜索栏、轮播图、宫格

效果展示 搜索栏制作 相关知识回顾 输入框组件TextInput 单行输入框类型.type(InputType.Normal)//基本输入框.type(InputType.Password)//密码.type(InputType.Email)//邮箱.type(InputType.Number)//数字.type(InputType.PhoneNumber)//电话号.type(InputType.Normal).type…

【折腾手机】一加6T刷机postmarketOS经历和体验

写在前面 到目前为止&#xff0c;我已经花了非常多的时间去学习和了解x86架构和RISC-V架构&#xff0c;对它们的指令集编程、指令格式的设计、编译套件的使用都亲自去体会和实践过&#xff0c;学到了很多的东西。但是对于离我们最近的arm架构却了解甚少。为什么说离我们最近呢…

Python | Leetcode Python题解之第199题二叉树的右视图

题目&#xff1a; 题解&#xff1a; class Solution:def rightSideView(self, root: TreeNode) -> List[int]:rightmost_value_at_depth dict() # 深度为索引&#xff0c;存放节点的值max_depth -1stack [(root, 0)]while stack:node, depth stack.pop()if node is not…

15 个适用于企业的生成式 AI 用例

作者&#xff1a;来自 Elastic Jennifer Klinger 关于生成式人工智能及其能做什么&#xff08;和不能做什么&#xff09;有很多讨论。生成式人工智能&#xff08;例如大型语言模型 - LLMs&#xff09;利用从大量训练数据中学习到的模式和结构来创建原创内容&#xff0c;而无需存…

weiyang**2.部署

一、官方文档 一键部署可以在 同机 快速搭建WeBASE管理台环境&#xff0c;方便用户快速体验WeBASE管理平台。 一键部署会搭建&#xff1a;节点&#xff08;FISCO-BCOS 2.0&#xff09;、管理平台&#xff08;WeBASE-Web&#xff09;、节点管理子系统&#xff08;WeBASE-Node-…