LeetCode-670. 最大交换-题解分析

题目来源

670. 最大交换

题目详情

给定一个非负整数,你至多可以交换一次数字中的任意两位。返回你能得到的最大值。

示例 1 :

输入: 2736
输出: 7236
解释: 交换数字2和数字7。

示例 2 :

输入: 9973
输出: 9973
解释: 不需要交换。

注意:

  1. 给定数字的范围是 [0, 108]

题解分析

本题一开始看没有明确的解题思路,会感觉无从下手。其实,本题的关键是越往后找到一个最大的数与越靠前的最小的数进行交换。

核心思路是将最靠后的最大的数,与最靠前的小于它的数交换(若存在),得到最大结果。具体的解法是使用贪心法求解最优数字交换方案。

本题使用贪心法需要考虑的两个核心思路是:

  • 选择哪个数作为候选数与前面的数交换?——将最靠后的数定为候选数,若它之前出现了更大的数,则更新候选数为该数。
  • 选择哪个数与候选数交换?——只有当候选数之前存在更小的数时,才需要交换这两数。若更靠前的位置出现小于候选数的数,则将它与候选数交换。

本题可以同时设置一个最大索引maxIdx以及一个候选索引candidate分别来记录右边最大值以及左边的候选值。字符串的遍历方向从右往左,不断比较记录最大值的位置,当遇到小于最大值的位置时,将其置为候选位置。

需要注意的是,这里在记录candidate候选位置的时候,同时需要记录一个endIdx指针,该指针记录了最大值索引。之所以不直接使用maxIdx表示最终需要交换的最大值索引,是因为前面可能出现比后面最大值还大的数字,这些数字不应该被替换,只需要替换最小值之后的候选位置。

java实现

class Solution {
    public int maximumSwap(int num) {
        String str = String.valueOf(num);
        int len = str.length();
        int maxIdx = len - 1;
        int candidate = -1;
        int endIdx = -1;
        for (int i = len-1; i >= 0; i--) {
            int number = str.charAt(i) - '0';
            int maxs = str.charAt(maxIdx) - '0';
            if (number > maxs) {
                maxIdx = i;
            } else if (number < maxs) {
                candidate = i;
                endIdx = maxIdx;
            }
        }
        if (candidate < 0) {
            return num;
        }
        String res = swap(str, candidate, endIdx);
        return Integer.parseInt(res);
    }

    private String swap(String str, int i, int j) {
        StringBuilder sb = new StringBuilder(str);
        sb.setCharAt(i, str.charAt(j));
        sb.setCharAt(j, str.charAt(i));
        return sb.toString();
    }
}
posted @ 2023-01-24 21:02  Garrett_Wale  阅读(207)  评论(0编辑  收藏  举报