Week10

问题描述

We have two integer sequences A and Bof 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, Aand 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].

思路

这道题主要的意思是,如何用最少的交换次数(交换 A[i] 和 B[i] )来使得A和B都是严格递增的。做这道题,我们要明确交换不止发生在出现 A[i] <= A[i-1] 或 B[i] <= B[i-1] 这些非递增的地方,在 A[i] > A[i-1],B[i] > B[i-1] 也是可以进行交换的。这就有点像背包问题,我们在每一个位置可以有两种情况,第一种是交换,第二种是不交换,所以我们需要两个一维数或是一个二维数组来记录每种情况下交换的最少次数。

在这道题里,子问题就是以 A[i],B[i] 结尾的子串的交换最少次数。对于每个子问题,我们需要考虑以下情况:

  1. 如果 A[i] > A[i-1],B[i] > B[i-1],我们可以交换 A[i] 和 B[i],也可以选择不交换
origin:
                        [2 3 5 7]
                         |
                        [0 2 4 5] 

swap:
			[2 2 5 7]         [0 2 5 7]
			   |         ->    | |
			[0 3 4 5]         [2 3 4 5]
            
为了保证递增,我们在交换A[i]与B[i]的时候,也要将A[i-1]与B[i-1]交换

not swap:
                        [2 3 5 7]
                         |
                        [0 2 4 5] 
  1. 如果 A[i] > B[i-1],B[i] > A[i-1],这个时候我们可以选择交换 A[i] 和 B[i],也可以选择交换 A[i-1] 和 B[i-1]
origin:
                        [1 3 6 5]
                               |
                        [1 2 4 7]
            
swap A[i] & B[i]:  

			[1 3 6 5]         [1 3 6 7]
			       |     ->          | 
			[1 2 4 7]         [1 3 4 5]
			
swap A[i-1] & B[i-1]:

			[1 3 6 5]         [1 3 4 5]
			     |       ->        | 
			[1 2 4 7]         [1 3 6 7]

在这种情况下,我们的 swap 可能是多余的,有可能我们在第一种情况下已经算出了更少的 swap 次数,所以我们要使用 min 得出最少的次数。

我们可以使用二维数组 dp,dp[0][i] 表示不交换 A[i]、B[i] 时的最少交换次数,dp[1][i] 表示交换A[i]、B[i]时的最少交换次数。

代码

class Solution {
public:
    int minSwap(vector<int>& A, vector<int>& B) {
        int len = A.size();
        // 初始化一个二维数组
        // dp[0][i] -> 对当前数字不进行swap
        // dp[1][i] -> 对当前数字进行swap
        vector<vector<int>> dp(2, vector<int>(len, len+1));
        
        // Initial
        dp[0][0] = 0; // no swap
        dp[1][0] = 1; // swap
        
       
        for(int i = 1; i < len; i++){
            if(A[i] > A[i-1] && B[i] > B[i-1]){
                // no swap
                dp[0][i] = dp[0][i-1];
                
                // swap A[i] & A[i-1]
                dp[1][i] = dp[1][i-1] + 1;
            }
            
            if(A[i] > B[i-1] && B[i] > A[i-1]){
                
                
                // no swap A[i] but swap A[i-1]
                dp[0][i] = min(dp[0][i], dp[1][i-1]);
                
                // swap A[i], not swap A[i-1]
                dp[1][i] = min(dp[1][i], dp[0][i-1]+1);
                
            }
        }
        
        return min(dp[0][len-1], dp[1][len-1]);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值