[LeetCode] Minimum Swaps To Make Sequences Increasing 使得序列遞增的最小交換

 

We have two integer sequences A and B of the same non-zero length.html

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.post

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和B,說是能夠在任意位置i交換A[i]和B[i]的值,咱們的目標是讓數組A和B變成嚴格遞增的數組,讓咱們求出最少須要交換的次數。博主最早嘗試了貪婪算法,就是遍歷數組,若是當前數字小於等於前面一個數字,那麼就交換一下,可是問題就來了,究竟是交換當前位置的數字,仍是前一個位置的數字呢,好比下面這個例子:url

0   4   4   5spa

0   1   6   8code

咱們究竟是交換4和1呢,仍是4和6呢,雖然兩種方法都能讓前三個數字嚴格遞增,可是若是交換了4和6,那麼第一個數組的最後一個5就又得交換了,那麼就要多交換一次,因此這個例子是交換4和1,可是對於下面這個例子:htm

0   4   4   7blog

0   1   6   5

那麼此時咱們就要交換4和6了,這樣只要交換一次就能使兩個數組都變成嚴格遞增的數組了。因此這道題用貪婪算法不work,咱們必須使用別的方法,那麼此時動態規劃Dynamic Programming就閃亮登場了。

像這種求極值的題目,不是Greedy就是DP啊,通常難題偏DP的比較多。而DP解法的第一步就是要肯定dp數組該怎麼定義,若是咱們定義一個一維數組dp,其中dp[i]表示使得範圍[0, i]的子數組同時嚴格遞增的最小交換次數,這樣的話狀態轉移方程就會十分的難寫,由於咱們沒有解耦合其內在的關聯。當前位置i是否交換,只取決於和前面一位是不是嚴格遞增的,而前一位也有交換或者不交換兩種狀態,那麼前一位的不一樣狀態也會影響到當前是否交換,這跟以前那道Best Time to Buy and Sell Stock with Transaction Fee就十分到相似了,那道題的股票也有保留或者賣出兩種狀態不停的切換。那麼這裏咱們也須要維護兩種狀態,swap和noSwap,那麼swap[i]表示範圍[0, i]的子數組同時嚴格遞增且當前位置i須要交換的最小交換次數,noSwap[i]表示範圍[0, i]的子數組同時嚴格遞增且當前位置i不交換的最小交換次數,兩個數組裏的值都初始化爲n。因爲須要跟前一個數字比較,因此咱們從第二個數字開始遍歷,那麼就須要給swap和noSwap數組的第一個數字提早賦值,swap[0]賦值爲1,由於其表示i位置須要交換,noSwap[0]賦值爲0,由於其表示i位置不須要交換。

好,下面來分析最難的部分,狀態轉移方程。因爲這道題限制了必定能經過交換生成兩個同時嚴格遞增的數組,那麼兩個數組當前位置和前一個位置之間的關係只有兩種,一種是不用交換,當前位置的數字已經分別大於前一個位置,另外一種是須要交換後,當前位置的數字才能分別大於前一個數字。那麼咱們來分別分析一下,若是當前位置已經分別大於前一位置的數了,那麼講道理咱們是不須要再進行交換的,可是swap[i]限定了咱們必需要交換當前位置i,那麼既然當前位置要交換,那麼前一個位置i-1也要交換,同時交換才能繼續保證同時遞增,這樣咱們的swap[i]就能夠賦值爲swap[i-1] + 1了。而noSwap[i]直接賦值爲noSwap[i-1]便可,由於不須要交換了。第二種狀況是須要交換當前位置,才能保證遞增。那麼swap[i]正好也是要交換當前位置,而前一個位置不能交換,那麼便可以用noSwap[i-1] + 1來更新swap[i],而noSwap[i]是不能交換當前位置,那麼咱們能夠經過交換前一個位置來一樣實現遞增,便可以用swap[i-1]來更新noSwap[i],當循環結束後,咱們在swap[n-1]和noSwap[n-1]中返回較小值便可,參見代碼以下:

 

解法一:

class Solution {
public:
    int minSwap(vector<int>& A, vector<int>& B) {
        int n = A.size();
        vector<int> swap(n, n), noSwap(n, n);
        swap[0] = 1; noSwap[0] = 0;
        for (int i = 1; i < n; ++i) {
            if (A[i] > A[i - 1] && B[i] > B[i - 1]) {
                swap[i] = swap[i - 1] + 1;
                noSwap[i] = noSwap[i - 1];
            }
            if (A[i] > B[i - 1] && B[i] > A[i - 1]) {
                swap[i] = min(swap[i], noSwap[i - 1] + 1);
                noSwap[i] = min(noSwap[i], swap[i - 1]);
            }
        }
        return min(swap[n - 1], noSwap[n - 1]);
    }
};

 

咱們能夠優化上面解法的空間複雜度,因爲當前位置的值只跟前一個位置相關,因此咱們並不須要保存整個數組,用四個變量來分別表示當前位置和前一個位置的各兩種狀態,能夠實現一樣的效果,參見代碼以下:

 

解法二:

class Solution {
public:
    int minSwap(vector<int>& A, vector<int>& B) {
        int n1 = 0, s1 = 1, n = A.size();
        for (int i = 1; i < n; ++i) {
            int n2 = INT_MAX, s2 = INT_MAX;
            if (A[i - 1] < A[i] && B[i - 1] < B[i]) {
                n2 = min(n2, n1);
                s2 = min(s2, s1 + 1);
            }
            if (A[i - 1] < B[i] && B[i - 1] < A[i]) {
                n2 = min(n2, s1);
                s2 = min(s2, n1 + 1);
            }
            n1 = n2;
            s1 = s2;
        }
        return min(n1, s1);
    }
};

 

相似題目:

Best Time to Buy and Sell Stock with Transaction Fee

 

參考資料:

https://leetcode.com/problems/minimum-swaps-to-make-sequences-increasing/solution/

https://leetcode.com/problems/minimum-swaps-to-make-sequences-increasing/discuss/119835/Java-O(n)-DP-Solution

https://leetcode.com/problems/minimum-swaps-to-make-sequences-increasing/discuss/120516/C++-solution-with-explanation

 

LeetCode All in One 題目講解彙總(持續更新中...)

相關文章
相關標籤/搜索