[Leetcode] 801. Minimum Swaps To Make Sequences Increasing 解题报告

题目

We have two integer sequences A and B of the same non-zero length.

We are allowed to swap elements A[i] and B[i].  Note that both elements are in the same index position in their respective sequences.

At the end of some number of swaps, A and B are both strictly increasing.  (A sequence is strictly increasing if and only if A[0] < A[1] < A[2] < ... < A[A.length - 1].)

Given A and B, return the minimum number of swaps to make both sequences strictly increasing.  It is guaranteed that the given input always makes it possible.

Example:
Input: A = [1,3,5,4], B = [1,2,3,7]
Output: 1
Explanation: 
Swap A[3] and B[3].  Then the sequences are:
A = [1, 3, 5, 7] and B = [1, 2, 3, 4]
which are both strictly increasing.

Note:

  • A, B are arrays with the same length, and that length will be in the range [1, 1000].
  • A[i], B[i] are integer values in the range [0, 2000].

思路

我们定义dp1[i]表示在不交换A[i]和B[i]的情况下,使得A的前i + 1个元素和B的前i + 1个元素严格递增的最小交换次数;定义dp2[i]表示在交换A[i]和B[i]的情况下,使得A的前i + 1个元素和B的前i + 1个元素严格递增的最小交换次数。那么递推可以分为两种可能性(由于题目保证一定有正确答案,所以以下两种可能性会至少满足一个,也有可能两个都满足):

1)A[i] > A[i - 1] && B[i] > B[i - 1]:这说明在维持第i对元素和第i - 1对元素同序的情况下可以满足条件,所以我们可以让dp1[i]和dp2[i]分别从INT_MAX降低到dp1[i - 1]和dp2[i - 1] + 1,也就是如果A[i - 1]和B[i - 1]交换了,那么我们也让A[i]和B[i]也交换;如果A[i - 1]和B[i - 1]维持原序,那么我们也让A[i]和B[i]维持原序。

2)B[i] > A[i - 1] && A[i] > B[i - 1]:这说明维护第i对元素和第i - 1对元素反序的情况下也可以满足条件,所以我们就看看能不能进一步降低dp1[i]和dp2[i]的数组:如果dp2[i - 1] < dp[i],那么说明交换第i - 1对元素之后,保持第i对元素的次序可以达到更优解;如果dp1[i - 1] + 1 < dp2[i],那么说明在维持第i - 1对元素的次序的情况下,交换第i对元素可以达到更优解。

算法的时间复杂度和空间复杂度都是O(n),不过我们发现dp1[i]和dp2[i]都只和dp1[i - 1],dp2[i - 1]有关,所以还可以将空间复杂度进一步降低到O(1),读者可以自行实现。

代码

class Solution {
public:
    int minSwap(vector<int>& A, vector<int>& B) {
        int length = A.size();
        vector<int> dp1(length, INT_MAX);               // dp1[i] is the minimal swap that retain A[i] and B[i]
        vector<int> dp2(length, INT_MAX);               // dp2[i] is the minimal swap that swap A[i] and B[i]
        dp1[0] = 0;
        dp2[0] = 1;
        for (int i = 1; i < length; ++i) {
            if (A[i] > A[i - 1] && B[i] > B[i - 1]) {   // the i-th can be the same as the (i - 1)th
                dp1[i] = dp1[i - 1];
                dp2[i] = dp2[i - 1] + 1;
            }
            if (B[i] > A[i - 1] && A[i] > B[i - 1]) {   // the i-th can also be different from the (i - 1)th
                dp1[i] = min(dp1[i], dp2[i - 1]);
                dp2[i] = min(dp2[i], dp1[i - 1] + 1);
            }
        }
        return min(dp1.back(), dp2.back());
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值