解题思路:使用两个状态量来存储信息:
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. 使序列递增的最小交换次数相关推荐

  1. Java实现 LeetCode 801 使序列递增的最小交换次数 (DP)

    801. 使序列递增的最小交换次数 我们有两个长度相等且不为空的整型数组 A 和 B . 我们可以交换 A[i] 和 B[i] 的元素.注意这两个元素在各自的序列中应该处于相同的位置. 在交换过一些元 ...

  2. LeetCode 801. 使序列递增的最小交换次数(动态规划)

    1. 题目 我们有两个长度相等且不为空的整型数组 A 和 B . 我们可以交换 A[i] 和 B[i] 的元素.注意这两个元素在各自的序列中应该处于相同的位置. 在交换过一些元素之后,数组 A 和 B ...

  3. leetcode算法题--使序列递增的最小交换次数★

    原题链接:https://leetcode-cn.com/problems/minimum-swaps-to-make-sequences-increasing/ 动态规划 dp[0]表示若当前位置不 ...

  4. Leetcode1963. 使字符串平衡的最小交换次数[C++题解]:贪心

    文章目录 题目 题解 题目 题目来源:https://leetcode-cn.com/problems/minimum-number-of-swaps-to-make-the-string-balan ...

  5. LeetCode 1674. 使数组互补的最少操作次数(差分思想)

    文章目录 1. 题目 2. 解题 1. 题目 给你一个长度为 偶数 n 的整数数组 nums 和一个整数 limit . 每一次操作,你可以将 nums 中的任何整数替换为 1 到 limit 之间的 ...

  6. LeetCode 995. K 连续位的最小翻转次数(差分思想)

    文章目录 1. 题目 2. 解题 1. 题目 在仅包含 0 和 1 的数组 A 中,一次 K 位翻转包括选择一个长度为 K 的(连续)子数组,同时将子数组中的每个 0 更改为 1,而每个 1 更改为 ...

  7. LeetCode 1864. 构成交替字符串需要的最小交换次数

    文章目录 1. 题目 2. 解题 1. 题目 给你一个二进制字符串 s ,现需要将其转化为一个 交替字符串 . 请你计算并返回转化所需的 最小 字符交换次数,如果无法完成转化,返回 -1 . 交替字符 ...

  8. LeetCode 945. 使数组唯一的最小增量

    945. 使数组唯一的最小增量 思路:预留多一点空间给它:用哈希表计算有多少个相同的值 class Solution { public:int minIncrementForUnique(vector ...

  9. LeetCode 1653. 使字符串平衡的最少删除次数(DP)

    文章目录 1. 题目 2. 解题 1. 题目 给你一个字符串 s ,它仅包含字符 'a' 和 'b'​​​​ . 你可以删除 s 中任意数目的字符,使得 s 平衡 . 我们称 s 平衡的 当不存在下标 ...

最新文章

  1. 时间序列竞赛炸榜技巧。
  2. 《Java 核心技术卷1 第10版》学习笔记------Object类的 equals 方法
  3. POJ1226 Substrings(二分+后缀数组)
  4. MySQL的基本查询(一)
  5. php 获取delete蚕丝_php结合Redis实现100万用户投票项目,并实时查看到投票情况的案例...
  6. access求斐波拉契数列_打印目录,斐波那契数列的递归与循环,牧场牛数
  7. one_code=soup.find('a',href=re.compile(rill)) NameError: name 're' is not defined
  8. Python中常用的一些库
  9. Glide4.0源码全解析(三),into()方法背后的故事
  10. 尚硅谷SpringCloud2020简单学习记录(个人用)33-39集
  11. word2010分页设置页眉
  12. Python入门教程三:显示'Welcome to Python'五次
  13. ElasticSerach 出现 high disk watermark [90%] exceeded on
  14. 一网打尽win10 Google Chrome浏览器打开后默认 桔梗 页面
  15. Linux-Samba文件共享服务
  16. 【Android 教程系列第 13 篇】在小米手机上使用安卓投屏软件 QtScrcpy ,为什么点击屏幕没有反应
  17. js数组常用方法(19种)|你会的到底有多少呢?
  18. C# 网络爬虫+HtmlAgilityPack+Xpath+爬虫工具类的封装的使用
  19. MUM System
  20. R语言 用nnet实现人工神经网络

热门文章

  1. [JavaScript]使用document.createDocumentFragment优化性能
  2. Nodejs 分布式事务
  3. 你解决的问题比你编写的代码更重要! 1
  4. Git如何进行分支合并
  5. 【Linux】设置虚拟内存
  6. HTML连载71-翻转菜单练习
  7. 02331 数据结构 学习小记 归纳总结
  8. element 组件中 el-form-item label= ‘vue介绍 (vue设置)‘ 强制换行
  9. 十大经典排序算法动画演示
  10. C#开发笔记之04-如何用C#优雅的计算个人所得税?