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