G
N
I
D
A
O
L

给你一个正整数数组 arr(可能存在重复的元素),请你返回可在 一次交换(交换两数字 arr[i]arr[j] 的位置)后得到的、按字典序排列小于 arr 的最大排列。

如果无法这么操作,就请返回原数组。

题目链接:https://leetcode.cn/problems/previous-permutation-with-one-swap/

# 解题思路

贪心:

  • 要是替换后的数比原始排序小,则能替换的是: arr[i] > arr[j] 且 i < j
  • 要使得替换后的数为最大的排序数,就要使替换的 i 尽可能靠后,因此可能最后往前变量数组,找到第一个满足 arr[i] > arr[i+1]
  • 再从 n-1 开始找第一个比 arr[i] 小的数 arr[j] ,因为 arr[j] 是比 arr[i] 小的最大的数

需要注意的是可能有多个 arr[j] ,应该取下标最小的,比如:

[4,1,1,1,4] ,应取 arr[1]arr[0] 交换

# 提交结果

image.png

# 代码

class Solution {
    public int[] prevPermOpt1(int[] arr) {
        if (arr.length < 2) return arr;
        
        int n = arr.length;
        for (int i = n - 2; i >= 0; --i) {
            if (arr[i] > arr[i + 1]) {
                int j = n - 1;
                int t = arr[i];
                while (j > i && arr[j] >= t) {
                    --j;
                }
                // 可能有与 arr [j] 相等的数,则替换位置更靠前的一个
                int k = j - 1;
                while (k > i && arr[j] == arr[k]) --k;
                arr[i] = arr[k + 1];
                arr[k + 1] = t;
                break;
            }
        }
        return arr;
    }
}
更新于 阅读次数

😉觉得写的还不错,请我喝杯咖啡吧😁

独步凌波 微信支付

微信支付

独步凌波 支付宝

支付宝