思路数组
1. 找到一个交换数Aspa
若是input各个数位上的值是按数位递增的,能够判断不能交换出数值更小的permutation。code
-> 反过来也就是说,若是input从右到左数位上的值所有是递减的就没有answer。blog
-> 说明若是不知足这个条件就说明能够进行置换,从右到左找到第一个违反递减顺序的数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; } };