原题描述
给你一个正整数数组 arr
(可能存在重复的元素),请你返回可在 一次交换(交换两数字 arr[i]
和 arr[j]
的位置)后得到的、按字典序排列小于 arr
的最大排列。如果无法这么操作,就请返回原数组。
示例 1:
输入:arr = [3,2,1] 输出:[3,1,2] 解释:交换 2 和 1示例 2:
输入:arr = [1,1,5] 输出:[1,1,5] 解释:已经是最小排列示例 3:
输入:arr = [1,9,4,6,7] 输出:[1,7,4,6,9] 解释:交换 9 和 7
解题方法
1. 逆序遍历数据,找到第一个递减arr[i - 1] > arr[i
]的数组索引。
if (arr[i - 1] > arr[i]) {
int index = max;
//和1-i交换的数据条件是已处理过的第一个小于i-1的数据
//arr[index]==arr[index-1] 找重复元素中下标最小的一个
while (arr[i - 1] <= arr[index]
||arr[index]==arr[index-1]) {//
index--;
}
/交换数据
int temp = arr[i - 1];
arr[i - 1] = arr[index];
arr[index] = temp;
break;
};
2.在数组已遍历的部分找到第一个小于i-1的数据,遇到重复元素选下标最小的一个。
//和1-i交换的数据条件是已处理过的第一个小于i-1的数据
//arr[index]==arr[index-1] 遇到重复元素选下标最小的一个
while (arr[i - 1] <= arr[index]
||arr[index]==arr[index-1]) {//
index--;
}
3.交换元素
//交换数据
int temp = arr[i - 1];
arr[i - 1] = arr[index];
arr[index] = temp;
Code
class Solution {
public static int[] prevPermOpt1(int[] arr) {
int l = arr.length;
//元素中处理数据
int max = l - 1;
//逆序处理数据,从尾部开始
for (int i = arr.length - 1; i > 0; i--) {
//计算最大值
max = arr[max] > arr[i] ? max : i;
//需要交换的数据是i-1
if (arr[i - 1] > arr[i]) {
int index = max;
//和1-i交换的数据条件是已处理过的第一个小于i-1的数据
//arr[index]==arr[index-1] 找重复元素中下标最小的一个
while (arr[i - 1] <= arr[index]
||arr[index]==arr[index-1]) {//
index--;
}
//交换数据
int temp = arr[i - 1];
arr[i - 1] = arr[index];
arr[index] = temp;
break;
};
}
return arr;
}
}