使序列递增的最小交换

Posted wuchanming

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使序列递增的最小交换相关的知识,希望对你有一定的参考价值。

我们有两个长度相等且不为空的整型数组 A 和 B 。

我们可以交换 A[i] 和 B[i] 的元素。注意这两个元素在各自的序列中应该处于相同的位置。

在交换过一些元素之后,数组 A 和 B 都应该是严格递增的(数组严格递增的条件仅为A[0] < A[1] < A[2] < … < A[A.length - 1])。

给定数组 A 和 B ,请返回使得两个数组均保持严格递增状态的最小交换次数。假设给定的输入总是有效的。

示例:

输入: A = [1,3,5,4], B = [1,2,3,7]
输出: 1
解释: 
交换 A[3] 和 B[3] 后,两个数组如下:
A = [1, 3, 5, 7] , B = [1, 2, 3, 4]
两个数组均为严格递增的。

注意:

A, B 两个数组的长度总是相等的,且长度的范围为 [1, 1000]。
A[i], B[i] 均为 [0, 2000]区间内的整数。

:这道题的确实有点难度,对于分析归纳能力要求挺高的。
刚开始吧,可能大家都想着使用类似贪心策略,就是遇到A[i - 1] >= A[i]这种逆序的时候,我们就将A[i]和B[i]进行交换,这时大家都会被一个测试示例难倒

0   4   4   5
0   1   6   8

第一次遇到A[i - 1] >= A[i]时,i = 2,按照贪心策略,我们应该交换A[2]和B[2],交换之后我们又发现A[3]出现了逆序,接着有需要交换A[3]和B[3],所以总共需要两次交换。蛋式这道题只需要交换1次,即我们交换A[1]和B[1]即可同时达到A、B严格递增。因此这种简单的贪心策略行不通。

经过查阅别人的实现,发现了一种动态规划的方法。

swapVec[ i ] 表示第 i 个元素进行交换,使A[0, i],B[0,i]严格单调递增的最小交换次数
keepVec[ i ] 表示第 i 个元素不进行交换,使A[0, i],B[0,i]严格单调递增的最小交换次数。

现在的问题就是我们如何找到状态转移方程。

(1)如果A[ i ] > A[ i - 1 ] && B[ i ]> B[ i - 1 ],对于这种情况,本身就是递增的,本不需要进行交换A[i]和B[i]
		swapVec[ i ]表示强制交换A[i]、B[i]即交换第i个元素,那么前一个位置i-1也要交换,同时交换才能继续保证同时递增,所以swapVec[ i ] = swapVec[ i - 1 ]+1
		keepVec[ i ]表示不交换A[i]、B[i],即不交换第i个元素,则第i-1个元素也不需要交换,keepVec[ i ]=keepVec[ i - 1 ]
(2)如果A[ i ] > B[ i - 1 ] && B[ i ]> A[ i - 1 ],对于此种情况,必须要交换A[i]、B[i]才能保持递增
		swapVec[i]正好也是要交换当前位置,而前一个位置不能交换,那么swapVec[ i ] = keepVec[ i - 1 ] +1
		keepVec[ i ]是不能交换当前位置,那么我们可以通过交换前一个位置来同样实现递增,即keepVec[ i ] = swapVec[ i - 1 ]
如果两种情况均成立时取较小值。

 

class Solution {
public:
    int minSwap(vector<int>& A, vector<int>& B) {
        int numsSize = A.size();
        //swapVec[ i ] 表示第 i 个元素进行交换,使A[0, i],B[0,i]严格单调递增的最小交换次数
    	//keepVec[ i ] 表示第 i 个元素不进行交换,使A[0, i],B[0,i]严格单调递增的最小交换次数。
        vector<int> swapVec(numsSize, INT_MAX), keepVec(numsSize, INT_MAX);
        swapVec[0] = 1;//初始化
        keepVec[0] = 0;
        for (int index = 1; index < numsSize; ++index){
            if (A[index] > A[index - 1] && B[index] > B[index - 1]){
                //如果第 i 个元素交换,那么第 i - 1 个元素一定是交换的;如果第 i 个元素没有交换,那么第 i - 1个元素一定没有交换
                swapVec[index] = swapVec[index - 1] + 1;
                keepVec[index] = keepVec[index - 1];
            }
            if (A[index] > B[index - 1] && B[index] > A[index - 1]){
                //如果第 i 个元素交换,那么第 i - 1 个元素一定是没有交换的;如果第 i 个元素没有交换,那么第 i - 1个元素一定是交换的
                swapVec[index] = min(swapVec[index], keepVec[index - 1] + 1);
                keepVec[index] = min(keepVec[index], swapVec[index - 1]);
            }
        }
        return min(swapVec.back(), keepVec.back());
    }
};

 

转载:https://blog.csdn.net/qq_41855420/article/details/90264842


以上是关于使序列递增的最小交换的主要内容,如果未能解决你的问题,请参考以下文章

力扣 每日一题 801. 使序列递增的最小交换次数难度:困难,rating: 2066(动态规划)

力扣 每日一题 801. 使序列递增的最小交换次数难度:困难,rating: 2066(动态规划)

数据结构与算法之深入解析“使序列递增的最小交换次数”的求解思路与算法示例

LeetCode 801 使序列递增的最小交换次数[动态规划] HERODING的LeetCode之路

LeetCode 801 使序列递增的最小交换次数[动态规划] HERODING的LeetCode之路

LeetCode 870. 优势洗牌(根据数值对索引排序)/ 856. 括号的分数(栈) / 801. 使序列递增的最小交换次数(动态规划)