1095.最大的交换
拖了好久终于决定开始刷题了。。
描述
给定一个非负整数,你可以交换两个数位至多一次来获得最大的合法的数。返回最大的合法的你能够获得的数。
样例
样例1:
输入: 2736
输出: 7236
解释: 交换数字2和数字7.
样例2:
输入: 9973
输出: 9973
解释: 不用交换.
注意事项
给定的数字在 [0, 10^8] 内。
暴力解法
最开始的思路:首先获取每位数字,然后找出最大的数字max,与从最高位顺序比较,一旦不相等则与其交换。【失败】
问题在于,当不相等的数在max右边,即会与比它位数低的数字交换,使num变小。
解决方法:把判断条件flagToExchange>0改成flagToExchange>flag。
再次出现问题:当比max小的数都在max右边时,不会交换,输出结果错误,例936->963不会进行交换。
解决方法:这时候考虑到递归算法,获取max后如未发生交换,则不考虑比max的位数高的数位,对剩下的数字进行相同计算,发生交换或剩下一位数时则停止递归。【Accept】
边界:num<0;
public class Solution {
/**
* @param num: a non-negative intege
* @return: the maximum valued number
*/
public int maximumSwap(int num) {
// Write your code here
if(num<10){
return num;
}
int[] digit = new int[8];
int digitCount = 0;
for(; num>0; num/=10,digitCount++){
digit[digitCount] = num % 10;
}
digitCount--;
change(digit,digitCount);
int ret = 0;
for(int i = digitCount; i >= 0; i--){
ret *= 10;
ret += digit[i];
}
return ret;
}
void change(int[] digit,int digitCount){
if(digitCount<=0){
return;
}
int max = digit[0], flag = 0;
for(int j = 1; j<=digitCount;j++){
if(digit[j]>max){
flag = j;
max = digit[j];
}
}
int flagToExchange = digitCount;
while(flagToExchange>flag&&n[flagToExchange]==max){
flagToExchange--;
}
if(flag == flagToExchange){
digitCount = flag-1;
change(digit,digitCount);
}else{
digit[flag] = digit[flagToExchange];
digit[flagToExchange] = max;
}
}
}
时间复杂度o(n^2)。
动态规划解法
max[]存储每个位数从低位到高位的最大值,maxIndex[]存储该值所在位置,从高位到低位查找i位置比max[i]小的数字,与maxIndex[i]的数字交换。
public class Solution {
/**
* @param num: a non-negative intege
* @return: the maximum valued number
*/
public int maximumSwap(int num) {
if(num<10){
return num;
}
int[] digit = new int[8];
int digitCount = 0;
for(; num > 0; num/=10, digitCount++){
digit[digitCount] = num % 10;
}
int[] max = new int[digitCount];
int[] maxIndex = new int[digitCount];
int maxFlag = max[0] = digit[0];
maxIndex[0] = 0;
for(int i = 1; i < digitCount; i++){
if(digit[i] > maxFlag){
maxFlag = max[i] = digit[i];
maxIndex[i] = i;
}else{
max[i] = max[i-1];
maxIndex[i] = maxIndex[i-1];
}
}
for(int i = digitCount - 1; i > 0; i--){
if(digit[i] < max[i]){
int temp = digit[maxIndex[i]];
digit[maxIndex[i]] = digit[i];
digit[i] = temp;
break;
}
}
int ret = 0;
for(int i = digitCount-1; i >= 0; i--){
ret *= 10;
ret += digit[i];
}
return ret;
}
}
时间复杂度o(n).