问题:
给定一个数组,求交换其中两个元素,使得到数组全部元素组成下一个较小的数值
Example 1: Input: [3,2,1] Output: [3,1,2] Explanation: Swapping 2 and 1. Example 2: Input: [1,1,5] Output: [1,1,5] Explanation: This is already the smallest permutation. Example 3: Input: [1,9,4,6,7] Output: [1,7,4,6,9] Explanation: Swapping 9 and 7. Example 4: Input: [3,1,1,3] Output: [1,3,1,3] Explanation: Swapping 1 and 3.
Example 5: Input: [5,3,1,1,3] Output: [5,1,3,1,3] Explanation: Swapping 1 and 3.
Note: 1 <= A.length <= 10000 1 <= A[i] <= 10000
解法:
巧用 栈
数值的下一个较小的数值,尽量在低位之间变换。
因此,我们考虑从后往前遍历。
基本方针为:
向前如果找到了比当前值A[cur]大的数值,交换。->下一个较小的数:用后位的小数换前位的大数
然后怎样,使得尽量变换差较小。
1⃣️首先被替换的高位,应该尽量在低位,即少往前移动。
2⃣️其次,再是要换成的数,尽量大。
solution:使用stack,保存从后往前,当前的cur,(如果A[cur-1]<A[cur]),将当前cur存入stack.push
使得当前的A[cur]越来越小,那么要被替换的高位 A[i] > A[cur]↓的可能就越大。这样首先保证了1⃣️
然后为了保证2⃣️,我们stack.pop,弹出尽量大的A[cur]↑,去替换到高位A[i]。
⚠️ 注意:在保存cur时,如果出现连续A[cur]相同的情况,尽量选取高位的cur,
因为将来高位要替换到cur的位置,和原来变化小的话,尽量越高越好。
代码参考:
1 class Solution { 2 public: 3 vector<int> prevPermOpt1(vector<int>& A) { 4 int n=A.size(); 5 if(n==1) return A; 6 stack<int> s; 7 s.push(n-1); 8 for(int i=n-2; i>=0; i--){ 9 int cur=s.top(); 10 if(A[i]<=A[cur]){ 11 while(i>=1 && A[i]==A[i-1]){ 12 i--; 13 } 14 s.push(i); 15 }else{ 16 s.pop(); 17 while(!s.empty()){ 18 if(A[i]>A[s.top()]){ 19 cur=s.top(); 20 s.pop(); 21 }else break; 22 } 23 swap(A[cur], A[i]); 24 return A; 25 } 26 } 27 return A; 28 } 29 };