LintCode 1016 · Minimum Swaps To Make Sequences Increasing (DP 好题)

文章描述了一个问题,给定两个整数序列A和B,允许交换相同位置上的元素,目标是找到最少的交换次数,使得两个序列都严格递增。文章提供了一种动态规划解法,通过计算两种情况下的最小交换次数来实现。

1016 · Minimum Swaps To Make Sequences Increasing
Algorithms
Medium

Description
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.

After 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.

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

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.
Example 2:

Input: A = [2,4,5,7,10], B = [1,3,4,5,9]
Output: 0

解法1:DP。
dp[i][0]: a, b前i个元素已经有序,且a[i],b[i]未交换
dp[i][1]: a, b前i个元素已经有序,且a[i],b[i]有交换
举例:a = [2, 5], b = [3, 4]
处理到i = 1时,
1)因为2<5, 3<4,
一种处理是什么都不用动,因为已经有序了。那么dp[i][0] = dp[i - 1][0];
还有一种处理时把2<->3,4<->5一起互换,这里不能只换一对,否则如果是a=[4,5],b=[3,4]就不能保证单调性了。所以dp[i][1] = dp[i - 1][1] + 1;
2)因为2<4,3<5,那么我们把2<->3或4<->5只换一对也是可以的。换两对的情况在1)已经处理了。
dp[i][0] = min(dp[i][0], dp[i - 1][1]); //换前面一对,后面一对不动。
dp[i][1] = min(dp[i][1], dp[i - 1][0] + 1); //前面一对不动,换后面一对。
注意:1)2)两个都要处理,要用两个if,不能用if else。

class Solution {
public:
    /**
     * @param a: an array
     * @param b: an array
     * @return: the minimum number of swaps to make both sequences strictly increasing
     */
    int minSwap(vector<int> &a, vector<int> &b) {
        int m = a.size(), n = b.size();
        //dp[i][0]: a, b前i个元素已经有序,且a[i],b[i]未交换
        //dp[i][1]: a, b前i个元素已经有序,且a[i],b[i]有交换
        vector<vector<int>> dp(m, vector<int>(2, INT_MAX / 3));
        dp[0][0] = 0; //a, b第0个元素不用交换
        dp[0][1] = 1; //a, b第0个元素交换也无妨,反正都只有一个元素,算有序。
        for (int i = 1; i < m; i++) {
            if (a[i - 1] < a[i] && b[i - 1] < b[i]) {
                dp[i][0] = min(dp[i][0], dp[i - 1][0]); //这里写成dp[i][0] = dp[i - 1][0]; 也可以
                dp[i][1] = min(dp[i][1], dp[i - 1][1] + 1); //这里写成dp[i][1] = dp[i - 1][1] + 1;也可以
            }
            if (a[i - 1] < b[i] && b[i - 1] < a[i]) {
                dp[i][0] = min(dp[i][0], dp[i - 1][1]);
                dp[i][1] = min(dp[i][1], dp[i - 1][0] + 1);
            }
        }
        return min(dp[n - 1][0], dp[n - 1][1]);
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值