题目原文
题目描述
给定一个非负整数,你至多可以交换一次数字中的任意两位。返回你能得到的最大值。
示例1:
输入: 2736
输出: 7236
解释: 交换数字2和数字7。
示例2:
输入: 9973
输出: 9973
解释: 不需要交换。
注意:
给定数字的范围是
[
0
,
108
]
[0, 108]
[0,108]。
解题思路
关键词:贪心
我们知道,将 n u m num num 转换成字符串 s s s 后, s [ i ] s[i] s[i] 和 s [ j ] s[j] s[j] 交换( i i i 表示高位, j j j 表示低位), i i i 的值越小就越好(位数越高), s [ j ] s[j] s[j] 的值越大就越好。
所以从低位开始循环:对于每一位上的数,若其值大于低位上每个数的最大值,则这个数和低位上任何一位数交换都会使总体数值变小,故不交换,更新最大值,进行高一位的判断即可。
若其值小于低位上每个数最大值,则这个数和这个最大值进行交换可以一定程度上的提升总体数值,但此时并不一定是最优答案,因为 i i i 的值越小越好(位数越高),则若能在更高位找到满足相同条件的数(若其值小于低位上每个数最大值),更高位交换操作效果更优。所以记录此时答案,若更高位有解则更新答案。一直到循环结束。
若其值等于低位上每个数最大值,则不进行任何操作,原因:首先,二者交换整体数值没有任何变换(两数相等,不妨设均等于 x x x);其次,若是将当前位更新为最大值所在位,则后面出现解的时候,是高位 i i i 和这位交换( a [ i ] < x a[i] < x a[i]<x),交换结果是 . . . . . . x . . . . . . a [ i ] . . . . . . x ......x......a[i]......x ......x......a[i]......x,不更新最大值所在位,则交换后为 . . . . . . x . . . . . . x . . . . . . a [ i ] ......x......x......a[i] ......x......x......a[i],因为 a [ i ] < x a[i] < x a[i]<x,所以前者整体值明显小于后者(左边为高位,右边为低位)。
综上,可得完整代码,见下方。
完整代码
class Solution {
public:
int maximumSwap(int num) {
string s = to_string(num); //将数字转换为字符串
int n = s.size(); //字符串长度
int idx1 = -1, idx2 = -1, max_idx = n - 1; //用来记录关键下标
for (int i = n - 1; i >= 0; i -- )
{
if (s[i] > s[max_idx]) max_idx = i;
else if (s[i] < s[max_idx])
{
idx1 = i;
idx2 = max_idx;
}
}
if (idx1 != -1 && idx2 != -1) swap(s[idx1], s[idx2]);
int res = stoi(s); //将字符串转换回数
return res;
}
};