[leetcode] 1503: Previous Permutation With One Swap

思路數組

1. 找到一個交換數Aspa

若是input各個數位上的值是按數位遞增的,能夠判斷不能交換出數值更小的permutation。code

-> 反過來也就是說,若是input從右到左數位上的值所有是遞減的就沒有answerblog

-> 說明若是不知足這個條件就說明能夠進行置換,從右到左找到第一個違反遞減順序的數A,須要用A與某一個數位交換input

    能夠證實:1) A右邊的數組是降序的,內部交換不能獲得更小的值;2) A左邊的數值權重更大,用A左邊的數去跟某個數位交換獲得的smaller value必定會比用A交換更小。數學

    因此用A交換才能獲得比input原數值更小的、數值最大的permutation。(又是更小又是最大什麼鬼好難表達io

2. 找到另外一個交換數B
class

另外一個交換數B必定是在A的右邊、數值比A小的數。總結

由於:1) 若是A與左邊的某個數C交換,要獲得比input原值更小的數那麼C必定比A大,在左邊數位上下降數值影響的權重必定比在靠右數位上的大。語言

         2) A是第一個違反從右到左降序規律的元素,A右邊必定存在比A數值更小的數。

又由於A右邊是從右到左降序排列的,B應該是其中比A小的數中最靠右的。但還有一點要考慮,A右邊並非嚴格降序排列的,可能存在與B相鄰且與B值相等的數D,這種狀況下應選擇這組相鄰相等的數中最靠左的。由於B和D必定比A小,要交換A和其中一個數得到最大的小值數(什麼鬼表達)應該要讓A和其中最靠左的數交換,把大數值的A放在權重儘可能高的位置上。

能夠進一步推定B是在A右邊、數值比A小的數中最靠右、若是有與其相等的相鄰數則選其中最靠左(什麼鬼真的好難表達

總結:從右到左找到首個違反降序規律的數A,找到A數值比A小的數中「最靠右、相等相鄰數中最靠左」的數B,交換AB。若是找不到A說明沒有可交換數位。

不會用數學語言證實我真的愈來愈垃圾了

 

code

 

class Solution {
public:
    vector<int> prevPermOpt1(vector<int>& A) {
        int N=A.size(), left;
        for (left=N-1;left>0;left--) {
            if (A[left-1]>A[left])
                break;
        }
        if (left==0)
            return A;
        --left;
        int right=N-1;
        while (A[right]>=A[left])
            --right;
        while (A[right]==A[right-1])
            --right;
        swap(A[left],A[right]);
        return A;
    }
};
相關文章
相關標籤/搜索