1053. Previous Permutation With One Swap

问题:

给定一个数组,求交换其中两个元素,使得到数组全部元素组成下一个较小的数值

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 };
原文地址:https://www.cnblogs.com/habibah-chang/p/13054333.html