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