持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第32天,点击查看活动详情
题目链接:670. 最大交换
题目描述
给定一个非负整数,你 至多 可以交换一次数字中的任意两位。返回你能得到的最大值。
提示:
- 给定数字的范围是
示例 1:
输入: 2736
输出: 7236
解释: 交换数字2和数字7。
示例 2:
输入: 9973
输出: 9973
解释: 不需要交换。
整理题意
题目给定一个 的非负整数,我们可以对这个整数中的任意两位进行一次交换,求进行一次操作后能够得到的最大值。
解题思路分析
方法一:暴力
首先能够想到的是暴力遍历所有可以交换的方法,取所有交换后的最大值即可。
贪心
我们从左到右遍历整数的每一位,如果在当前位右边有比当前位数字大的数字,我们将其与当前位进行交换即可。需要注意的是,如果右边有多位数字大于当前位数字,我们要选择最大的一位,且如果最大的一位有多个,我们需要选择最右边的一个。
具体实现
方法一:暴力
- 首先将整数转换成字符串进行处理;
- 双层循环遍历所有可以交换的方法;
- 利用一个变量记录交换后的最大值;
- 最后再将字符串转换成整数即可。
方法二:贪心
- 首先可以预处理出每一位的右边(包含自己)最大且最靠右的数字下标,从右到左记录遍历过的最大数字即可(需要注意当数字相同时需要取靠右的)
- 从左到右遍历每一位数字,当遇到当前位后面存在比当前位大的数字时,直接进行交换,然后跳出循环;
- 输出交换后的数字即可。
复杂度分析
- 时间复杂度:
- 暴力:,其中整数 为给定的数字。 转换为十进制数,有 个数字,一共有 种不同的交换方法,每种方法需要重新构造一个新的整数,需要的时间为 ,因此总的时间复杂度为 。
- 贪心:,其中整数 为给定的数字。 转换为十进制数,有 个数字,需要遍历一次所有的数字即可。
- 空间复杂度:
- 暴力:,其中整数 为给定的数字。 转换为十进制数,有 个数字,需要保存 所有的数字。
- 贪心:,其中整数 为给定的数字。 转换为十进制数,有 个数字,需要保存 所有的数字。
代码实现
暴力
class Solution {
public:
int maximumSwap(int num) {
string temp = to_string(num);
int n = temp.size();
string m = temp;
for(int i = 0; i < n; i++){
for(int j = i + 1; j < n; j++){
swap(temp[i], temp[j]);
m = max(m, temp);
swap(temp[i], temp[j]);
}
}
return stoi(m);
}
};
贪心
class Solution {
public:
int maximumSwap(int num) {
string temp = to_string(num);
int n = temp.size();
int idx[n];
idx[n - 1] = n - 1;
for(int i = n - 2; i >= 0; i--){
if(temp[i] <= temp[idx[i + 1]]){
idx[i] = idx[i + 1];
}
else idx[i] = i;
}
for(int i = 0; i < n; i++){
if(temp[i] < temp[idx[i]]){
swap(temp[i], temp[idx[i]]);
break;
}
}
return stoi(temp);
}
};
总结
- 该题的难点在于贪心的方法;
- 暴力搜索每一种交换方法比较容易想到,但是并不是最优解;
- 在处理整数时,将其转换为字符串的形式进行处理比较方便。
- 测试结果:
结束语
每个人都拥有时间,但不是每个人都懂的珍惜。别等到暮年才感叹年华的流逝。把握当下,不要把最精彩的人生过成最无奈的遗憾。新的一天,加油!