[Leetcode] 801. Minimum Swaps To Make Sequences Increasing 解題報告

題目

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());
    }
};
發佈了742 篇原創文章 · 獲贊 72 · 訪問量 32萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章