[M模拟] lc670. 最大交换(模拟+贪心+技巧)

文章目录

    • 1. 题目来源
    • 2. 题目解析

1. 题目来源

链接:670. 最大交换

2. 题目解析

比较简单直接的思路,但容易出错,从通过率 48.8% 就能看出来端倪…

WA 了两次…

思路1:

  • 数字不会爆 int,直接数位分解到 vector 中做处理。
  • 从高数位依次向后看,如果找到了一个底数位中的最大数,则跟我当前的高数位交换即会让结果变大。实际上也就提前找到了结果。直接返回新结果即可。
  • 否则,返回原值。

思路很简单,但有两个坑点吧:

  • 如果,高数位向后找的低数位中,有多个相同的低数位都比高数位值大,那么我们应该尽量向后取值。如:1993,我们应该取最低数位的 9,结果为:9913,而不是 9193。
  • 如果,高数位的值和低数位中的最大值是相等的,实际上不需要交换,也不需要退出。应该将待判断的高数位继续向后移动。如:98368,第二个 8 与末尾的 8 相等,此时不应该交换,返回结果,而是继续向后找,结果应当为 98863。

就这这两个地方 WA 了两次…大意了…


思路2:
实际上最多就 8 位数,最多两两交换,那么也就是 C(8, 2) = 28 种情况呗,直接暴力遍历数位两两交换,维护一个最大值即可。

这里显然,使用字符串会方便很多。也是常用技巧之一。


思路3:
基于思路 1,实际上我们根本不需要从高位到低位去遍历,我们只需要让 右边最大的数字和左边最小的数字做一个交换就行了。

这个思路看 官解、灵神 的讲解即可。感觉很难想到…


  • 时间复杂度 O ( n ) O(n) O(n)
  • 空间复杂度 O ( 1 ) O(1) O(1)

思路1:
丑陋的代码:

class Solution {
public:
    int maximumSwap(int num) {
        vector<int> nums;

        int cnt = 0, t = num;
        while (t) {
            nums.push_back(t % 10);
            t /= 10;
        }
        reverse(nums.begin(), nums.end());

        int n = nums.size();
        for (int i = 0; i < n; i ++ ) {
            int x = nums[i], cur = nums[i], idx = -1;
            for (int j = i + 1; j < n; j ++ ) {
                if (nums[j] >= cur) {   // 尽量往后取, eg: 1993
                    cur = nums[j], idx = j;
                }
            }

            if (x == cur) continue; // 如果相等时,则不需要操作 eg: 98368

            if (idx != -1) {
                nums[idx] = x;
                nums[i] = cur;

                int res = 0;
                for (int k = 0; k < n; k ++ ) res = res * 10 + nums[k];

                return res;
            }
        }

        return num;
    }
};

思路2:

class Solution {
public:
    int maximumSwap(int num) {
        string charArray = to_string(num);
        int n = charArray.size();
        int maxNum = num;
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                swap(charArray[i], charArray[j]);
                maxNum = max(maxNum, stoi(charArray));
                swap(charArray[i], charArray[j]);
            }
        }
        return maxNum;
    }
};

思路3:

class Solution {
public:
    int maximumSwap(int num) {
        string charArray = to_string(num);
        int n = charArray.size();
        int maxIdx = n - 1;
        int idx1 = -1, idx2 = -1;
        for (int i = n - 1; i >= 0; i--) {
            if (charArray[i] > charArray[maxIdx]) {
                maxIdx = i;
            } else if (charArray[i] < charArray[maxIdx]) {
                idx1 = i;
                idx2 = maxIdx;
            }
        }
        if (idx1 >= 0) {
            swap(charArray[idx1], charArray[idx2]);
            return stoi(charArray);
        } else {
            return num;
        }
    }
};

你可能感兴趣的:(LeetCode,算法)