670. 最大交换

1.题目介绍

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

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

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

注意:
给定数字的范围是 [0, 10^8]

2.题解

2.1 暴力枚举

思路

我们可以将int类型数字先转换为字符串,然后将其某两位进行交换,再通过stoi得到交换后的值。
注意这里给定数字的范围是 [0, 10^8],也就是说最多是个8位数,任意两个数字交换一次最多有 C^2_8 = 8*7/2 = 28 种不同的交换方法,我们完全可以将所有情况枚举出来,取最大值即可。

代码

注意这里to_string, stoi等函数的应用

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

2.2 贪心算法

思路


根据以上等式我们可以看出,若使得 val 的值最大,应依次满足如下条件:

代码

1.这里要注意首先就要保证 k < j(按照索引大小来的!!!小的是高位) 的条件,我第一次代码错误就是因为没有考虑这点
对于98368,最后由于9 > 8, j直接传到索引0上,而str[k]依旧等于3, 此时 j < k违反
2.如何解决这个问题呢? 就是要求k和j的移动必须同步,只有在前方还有可能小于nums[maxLen]的数情况下,j才会移到maxLen处,k则移到那个小于maxLen的地方即可
所以我们再设置一个记录变量maxLen用于记录潜在的较大值点,具体是否移动,看是否存在str[i] < str[maxLen]
3.注意这里str[i] < str[maxLen] 而不是直接使用else,因为对于str[i] == str[maxLen] 的情况不可以移动,否则不满足最大条件
注意我们这里的四个条件的两个:1.最优的交换一定需要满足 dj > dk 2.在同样大小的数字 dj 时,应使得索引 j 越小从而使得 val 越大;
对于98368,若是按str[i] <= str[maxLen] 条件,在之前会达到 k = 2(对应3), j = 4(对应8)
接下里由于str[i] == str[maxLen] =》 k = i = 1(对应8), j = 4(对应8) ,最后这两个交换大小不变,这并不是我们想要的,不能求到最大值!!!
4.对于这里的四个条件
4.1 最优的交换一定需要满足 dj > dk(隐含条件 k > j) 》 通过 if(str[i] < str[maxLen]) 满足 因为此时 dj = str[i] < dk = str[maxLen];
4.2 在满足 dj > dk时,应该保证索引 k 越大从而使得数字 val 越大; 》 这里是通过从右向左遍历实现的,若是左边有满足dj>dk时,左边会覆盖右边的索引k,使得索引k尽可能的“大”(从索引角度来说是小)
4.3 在同样大小的数字 dk 时,应使得数字 dj 越大从而使得 val 越大;
》 这里通过maxLen记录,保证和dk交换的dj是右边最大的dj
4.4 在同样大小的数字 dj 时,应使得索引 j 越小从而使得 val 越大;
》 这里是从右向左遍历,同时if(str[i] > str[maxLen])的条件
而不是if(str[i] >= str[maxLen])的条件,保证最大的dj是偏右的。

class Solution {l
public:
    int maximumSwap(int num) {
        string str = to_string(num);
        int n= str.size();
        // int j = n - 1, k = -1;
        // for(int i = n - 2; i >= 0; i--){
        //     if(str[i] > str[j]){
        //         j = i;
        //     }
        //     else if(str[i] < str[j]) k = i;      
        // }
        int maxLen = n - 1;
        int left = -1, right = -1;
        for(int i = n - 2; i >=0; i--){
            if(str[i] > str[maxLen]) maxLen = i;
            else if(str[i] < str[maxLen]){
                left = i;
                right = maxLen;
            }
        }
        
        if (left >= 0){
            swap(str[left], str[right]);
            return stoi(str);
        }
        else return num;
    }
};
posted @ 2024-01-23 00:24  DawnTraveler  阅读(19)  评论(0编辑  收藏  举报