问题描述
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]
.
思路
这道题主要的意思是,如何用最少的交换次数(交换 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] 结尾的子串的交换最少次数。对于每个子问题,我们需要考虑以下情况:
- 如果 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]
- 如果 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]);
}
};