[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;
    }
};
相关文章
相关标签/搜索