1095.最大的交换

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).

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值