LeetCode#670 Maximum Swap题解(C++版)

题干

Given a non-negative integer, you could swap two digits at most once to get the maximum valued number. Return the maximum valued number you could get.
原题题干

难度

中等(Medium)

题干解析

给你一个非负整数,你有一次机会来移动这个数中的任意两位,使得得到的新的数字是最大的。规定输入的数字在0~10^8范围内。

解题思路

互换数的某两位,使原数变大,前提是这两位中低位的数大于高位的数。
要找到最大的答案,无疑要先从最高位出发,找到原数各个位中最大的数,这里我们把找到的这个位叫作m位,m位的数最大(m可以是个、十、百、千…),将m位的数与最高位互换,可以获得最大的数。不过,要考虑特殊情况,当m位恰好是最高位(或者m位的数与最高位的一样大,此处易错)不需移动,那么我们还有移动的机会,应该接着考虑把各个位中第二大的数放在第二高位,以此类推,若第二大的已然位于第二高位,那么接着考虑第三大,第四大……

所以我们的代码大致分为三个步骤:
第一步,我们先要对数字进行处理,提取出各个位的数字,放在数组里面。
第二步,通过遍历循环,查询要用来移位的数。
第三步,移位,得到答案,恢复成整数。

易错点

有一种情况要当心(造成博主之前Wrong Answer的原因=。=),当原数各个位中最大(或者第n大)的数有多个时,比如90880,第二大的数是8,有两个,那么我们应该把十位的8换到千位(变成98800),而不是把百位的8放到千位(变成98080)。所以在搜索最大(第n大时),遇到相同大小的数,我们优先考虑低位的,将更低位的换到高位才能得到更大的结果。氮素!这里还有一个坑!如9890这个数,千位和十位有相同的最大数9,如果我们优先考虑低位的最大数,那么这个时候我们会识别出十位的9最大(即m位是十位),并傻乎乎地把它与千位互换,这样就白白浪费了我们移动的机会,正确的做法应该是把十位和百位互换,变成9980。所以,为了避过这个坑,我们还必须在识别原数各个位最大(或第n大)的时候多加一个判断,若找到的最大数(m位的数)与最高位的数一致,那么我们就不要互换。

代码

class Solution {
public:
int maximumSwap(int num) {
    int num_array[9];  // 用来存放原数的各个位的数
    int temp = num;
    int i = 0;
    while (num > 0) {   // 对原数进行处理,分离出各个位的数
        num_array[i] = num % 10;
        num /= 10;
        i++;
    }
    int digit = i;  // 此数字的位数 

    int max_index = i;
    while (max_index == i && i > 0) { 
        // 循环找寻要互换的位max_index和i
        i--;//i原代表最高位,若最高位不需互换,i降为第二高位,依此类推
        max_index = i;
        for (int j = i; j >= 0; j--) {
            if (num_array[j] > num_array[max_index] || (num_array[j] == num_array[max_index] && max_index != i)) {  // 注意这个判断,对应易错点的介绍
                max_index = j;
            }
        }
    }

    if (max_index == i && i == 0) { // 如果发现不需要互换
        return temp;
    } else {   // 如果需要互换
        // 先进行互换
        int a = num_array[max_index];
        num_array[max_index] = num_array[i];
        num_array[i] = a;

        // 后恢复为整数
        int ans = 0;
        for (int k = 0; k < digit; k++) {
            ans += num_array[k] * pow(10, k);
        }
        return ans;
    }
}
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值