2023-04-03每日一题
一、题目编号
1053. 交换一次的先前排列
二、题目链接
三、题目描述
给你一个正整数数组 arr(可能存在重复的元素),请你返回可在 一次交换(交换两数字 arr[i] 和 arr[j] 的位置)后得到的、按字典序排列小于 arr 的最大排列。
如果无法这么操作,就请返回原数组。
提示:
- 1 <= arr.length <= 104
- 1 <= arr[i] <= 104
四、解题代码
class Solution {
void swap(int &x, int &y){
x = x ^ y;
y = x ^ y;
x = x ^ y;
}
public:
vector<int> prevPermOpt1(vector<int>& arr) {
int n = arr.size();
for(int i = n-2; i >= 0; --i){
int index = -1;
if(arr[i] > arr[i+1]){
for(int j = n-1; j >= i + 1; --j){
if(arr[j] == arr[j-1] || arr[j] >= arr[i]){
continue;
} else{
index = j;
break;
}
}
}
if(index != -1){
swap(arr[i], arr[index]);
break;
}
}
return arr;
}
};
五、解题思路
(1)逆序查询,查询数右边的数字皆是无法作为左侧被交换的数字。
(2)当查询的数字大于右侧的数字,才可能出现字典序小的情况。
(3)此时再进行逆序查询,查询到一个数不等于该数前面的数并且该数字小于左端要交换的数字,此时标记位置。
(4)如果标记位置为-1则意味着不可交换,如果有了标记则进行交换。