题目:
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());
}
};