题干
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;
}
}
};