leetcode - 801. 使序列递增的最小交换次数
解题思路:使用两个状态量来存储信息:
swap[i]表示交换A和B中第i个数字,A和B中前i个数字达到严格递增所需要的最小交换次数。
keep[i]表示不交换A和B中第i个数字,A和B中前i个数字达到严格递增所需要的最小交换次数。
对于A和B中的第i个数字,要考虑两种情况。
第一种情况是A[i]>A[i-1] && B[i]>B[i-1],同时有A[i]>B[i-1] && B[i]>A[i-1],这时候对于swap[i]和keep[i]的状态转移方程如下:
if(a[i]>a[i-1] && b[i]>b[i-1])
{if(a[i]>b[i-1] && b[i]>a[i-1]){swap[i] = min(swap[i-1],keep[i-1]) + 1;keep[i] = swap[i] - 1;}
}
在符合上面两个条件的情况下,如果要交换A和B中的第i个数字,则可以找min(swap[i-1],keep[i-1])+1,因为不管是交换第i-1个数字还是保持第i-1数字,对于是否交换第i个数字都没有影响,因为都符合条件,因此我们选择swap[i-1]和keep[i-1]中较小的那个值,然后加1。这样就得到了在符合条件下的交换第i个数字所需要的最小交换次数。
同理,对于keep[i],因为不管是交换第i-1个数字得到的swap[i-1]还是不交换第i-1个数字得到的keep[i-1],都对keep[i]没啥影响,因此我们选择swap[i-1]和keep[i-1]中较小的那个,并赋值给keep[i]。也可以表示为keep[i] = swap[i] - 1。具体的形式就和上面的代码一下。
要是符合条件A[i]>A[i-1] && B[i]>B[i-1],但是不符合条件A[i]>B[i-1] && B[i]>A[i-1]时,我们需要考虑另外的情况,具体的C++代码如下:
if(a[i]>a[i-1] && b[i]>b[i-1])
{if(a[i]>b[i-1] && b[i]>a[i-1]) //两种情况都符合{swap[i] = min(swap[i-1],keep[i-1]) + 1; keep[i] = swap[i] - 1;}else //不符合a[i]>b[i-1] && b[i]>a[i-1]{swap[i] = swap[i-1] + 1;keep[i] = keep[i-1];}
}
在符合a[i]>a[i-1] && b[i]>b[i-1]条件,但是不符合a[i]>b[i-1] && b[i]>a[i-1]条件时,要找swap[i]的状态转移方程,可以分析一下,因为不符合a[i]>b[i-1] && b[i]>a[i-1],如果我们交换了第i个数字,那么前i个数字必定不符合严格递增关系。如果要变成符合严格递增关系的子集,则要将前i-1个数组进行变换。很幸运,swap[i-1]表示的是交换第i-1个数字得到严格递增关系的数组所需的最小交换次数。那么就可以得到swap[i] = swap[i-1] + 1。
同理,对于keep[i],因为第i个数字不符合a[i]>b[i-1] && b[i]>a[i-1],要求第i个数字保持不变得到前i个数组严格递增所需的最小交换次数,则分析前i-1个数组中的swap[i-1]和keep[i-1]。可以得知keep[i] = keep[i-1] + 1。意思是要求第i个数字不变的最小交换次数,则可以在第i-1个数字不变得到递增数组所需的最小交换次数上加1。注意不能用到swap[i-1],因为swap[i-1]是交换了第i-1个数字的。当交换第i-1个数字时,如果第i个数字不交换,是没办法得到严格递增数组的。
第二种情况是A[i]<A[i-1] || B[i]<B[i-1],这种情况下考虑swap[i]和keep[i]的状态转移方程,根据上面的分析,我们可以简单地得到:
swap[i] = keep[i-1]+1;
keep[i] = swap[i-1];
这两个状态转移方程的意思是,如果交换第i个数字,则是在第i-1个数字不交换得到递增数组的最小交换次数的程度上+1。同理,如果不交换第i个数字,则因为违反了严格递增关系,需要把前i-1个数组进行变换,那么恰好swap[i-1]的意思就是交换第i-1个数字得到严格递增数组所需的最小交换次数,那么就可以得到keep[i] = swap[i-1];
综上分析,可以得到整体C++代码如下:
class Solution {
public:int minSwap(vector<int>& a, vector<int>& b) {int length = a.size();vector<int> swap(length,1); //用于存储交换第i个数字,使前i个数字达到严格递增数组所需的最小交换次数vector<int> keep(length,0); //用于存储不交换第i个数字,使前i个数字达到严格递增数组所需的最小交换次数for(int i=1;i<length;i++){if(a[i]>a[i-1] && b[i]>b[i-1]) //如果A(B)中第i个数字和A(B)中第i-1个数字符合严格递增关系{if(a[i]>b[i-1] && b[i]>a[i-1]) //如果A(B)中第i个数字和B(A)中第i-1个数字符合严格递增关系{ swap[i] = min(swap[i-1],keep[i-1]) + 1;keep[i] = swap[i] - 1;}else //如果A(B)中第i个数字和B(A)中第i-1个数字不符合严格递增关系{swap[i] = swap[i-1] + 1;keep[i] = keep[i-1];}}else //如果A(B)中第i个数字和A(B)中第i-1个数字不符合严格递增关系{swap[i] = keep[i-1] + 1;keep[i] = swap[i-1];}}return min(swap[length-1],keep[length-1]); //返回交换或者不交换两者之间的较小的值}
};
这里解题的关键是要理解swap[i]和keep[i]代表的意义,并理解swap[i-1]、swap[i]、keep[i-1]、keep[i]之间的关系。
leetcode - 801. 使序列递增的最小交换次数相关推荐
- Java实现 LeetCode 801 使序列递增的最小交换次数 (DP)
801. 使序列递增的最小交换次数 我们有两个长度相等且不为空的整型数组 A 和 B . 我们可以交换 A[i] 和 B[i] 的元素.注意这两个元素在各自的序列中应该处于相同的位置. 在交换过一些元 ...
- LeetCode 801. 使序列递增的最小交换次数(动态规划)
1. 题目 我们有两个长度相等且不为空的整型数组 A 和 B . 我们可以交换 A[i] 和 B[i] 的元素.注意这两个元素在各自的序列中应该处于相同的位置. 在交换过一些元素之后,数组 A 和 B ...
- leetcode算法题--使序列递增的最小交换次数★
原题链接:https://leetcode-cn.com/problems/minimum-swaps-to-make-sequences-increasing/ 动态规划 dp[0]表示若当前位置不 ...
- Leetcode1963. 使字符串平衡的最小交换次数[C++题解]:贪心
文章目录 题目 题解 题目 题目来源:https://leetcode-cn.com/problems/minimum-number-of-swaps-to-make-the-string-balan ...
- LeetCode 1674. 使数组互补的最少操作次数(差分思想)
文章目录 1. 题目 2. 解题 1. 题目 给你一个长度为 偶数 n 的整数数组 nums 和一个整数 limit . 每一次操作,你可以将 nums 中的任何整数替换为 1 到 limit 之间的 ...
- LeetCode 995. K 连续位的最小翻转次数(差分思想)
文章目录 1. 题目 2. 解题 1. 题目 在仅包含 0 和 1 的数组 A 中,一次 K 位翻转包括选择一个长度为 K 的(连续)子数组,同时将子数组中的每个 0 更改为 1,而每个 1 更改为 ...
- LeetCode 1864. 构成交替字符串需要的最小交换次数
文章目录 1. 题目 2. 解题 1. 题目 给你一个二进制字符串 s ,现需要将其转化为一个 交替字符串 . 请你计算并返回转化所需的 最小 字符交换次数,如果无法完成转化,返回 -1 . 交替字符 ...
- LeetCode 945. 使数组唯一的最小增量
945. 使数组唯一的最小增量 思路:预留多一点空间给它:用哈希表计算有多少个相同的值 class Solution { public:int minIncrementForUnique(vector ...
- LeetCode 1653. 使字符串平衡的最少删除次数(DP)
文章目录 1. 题目 2. 解题 1. 题目 给你一个字符串 s ,它仅包含字符 'a' 和 'b' . 你可以删除 s 中任意数目的字符,使得 s 平衡 . 我们称 s 平衡的 当不存在下标 ...
最新文章
- 时间序列竞赛炸榜技巧。
- 《Java 核心技术卷1 第10版》学习笔记------Object类的 equals 方法
- POJ1226 Substrings(二分+后缀数组)
- MySQL的基本查询(一)
- php 获取delete蚕丝_php结合Redis实现100万用户投票项目,并实时查看到投票情况的案例...
- access求斐波拉契数列_打印目录,斐波那契数列的递归与循环,牧场牛数
- one_code=soup.find('a',href=re.compile(rill)) NameError: name 're' is not defined
- Python中常用的一些库
- Glide4.0源码全解析(三),into()方法背后的故事
- 尚硅谷SpringCloud2020简单学习记录(个人用)33-39集
- word2010分页设置页眉
- Python入门教程三:显示'Welcome to Python'五次
- ElasticSerach 出现 high disk watermark [90%] exceeded on
- 一网打尽win10 Google Chrome浏览器打开后默认 桔梗 页面
- Linux-Samba文件共享服务
- 【Android 教程系列第 13 篇】在小米手机上使用安卓投屏软件 QtScrcpy ,为什么点击屏幕没有反应
- js数组常用方法(19种)|你会的到底有多少呢?
- C# 网络爬虫+HtmlAgilityPack+Xpath+爬虫工具类的封装的使用
- MUM System
- R语言 用nnet实现人工神经网络
热门文章
- [JavaScript]使用document.createDocumentFragment优化性能
- Nodejs 分布式事务
- 你解决的问题比你编写的代码更重要! 1
- Git如何进行分支合并
- 【Linux】设置虚拟内存
- HTML连载71-翻转菜单练习
- 02331 数据结构 学习小记 归纳总结
- element 组件中 el-form-item label= ‘vue介绍 (vue设置)‘ 强制换行
- 十大经典排序算法动画演示
- C#开发笔记之04-如何用C#优雅的计算个人所得税?