LeetCode-Medium-Java-Maximum Swap


交换一次得到最大值

题目描述:

Given a non-negative integer, you could swap two digits at most once to get the maximum valued number. Return the maximum valued number you could get.

Example 1:

Input: 2736
Output: 7236
Explanation: Swap the number 2 and the number 7.

Example 2:

Input: 9973
Output: 9973
Explanation: No swap.

Note:

  1. The given number is in the range [0, 108]
刚开始看见题目,以为很简单,只要找到每位中的最大值,然后与最高位交换即可。,例如:2376,交换完后是:7326。代码(这是错误示范哈):
public int maximumSwap(int num) {
        if(num<10){
            return num;
        }
        int result=0;
        int n=10;
        int max=num%n;
        int len=0;
        int index=0;
        int[] numArr=new int[20];
        numArr[0]=max;
        while(num/n!=0){
            num=num/n;
            len++;
            numArr[len]=num%n;
            if(max<numArr[len]){
                max=numArr[len];//记录最大值
                index=len; //记录最大值的位置
            }          
        }
        numArr[index]=numArr[len]; //将最高位复制给最大值所在的位置
        numArr[len]=max; //将最大值赋值给最高位
        for(int i=0;i<=len;i++){
            System.out.println(numArr[i]);
            result=result+numArr[i]*(int)Math.pow(10,i);
        }
        return result;
    }

可是针对9362这样的整数最高位已经是最大了,还是可以交换得到更大值:9632。

主要思路:就是把大数换到前面去,所以还是从头开始遍历,一旦发现可以交换的值就结束了。

改进:遍历每一位去执行刚刚的算法,即:若第一位已经是最大值,则第一位无需交换;接下来判断第二位与剩余位相比是否是最大值,若不是,则记录最大值的位置,与第二位交换;若是,则判断下一位;直至最后一位。得到代码如下(还是错误示范):

 public int maximumSwap(int num) {
        if(num<10){
            return num;
        }
        String numStr=num+"";
	char[] numArr=numStr.toCharArray(); //将数字转换为字符数组
        int swapIndex=0; //记录被交换值的索引位置
        char swapValue='a'; //记录被交换的值
        for(int i=0;i<numArr.length;i++){  //遍历每一位是否是最大值
            swapValue=numArr[i];
            swapIndex=i;
            for(int j=i+1;j<numArr.length;j++){   //遍历当前位后面的每一位,出现大于它的值就更新,并记录这个最大值的位置            
                if(numArr[i]<numArr[j]){  
                    numArr[i]=numArr[j];
                    swapIndex=j;
                }
            }
            if(i!=swapIndex){  //若没有比当前位大的值,则swapIndex等于i, 在每次循环前已经赋值啦 否则出现了可以替换的值,结束循环
                break;
            }
        }
        numArr[swapIndex]=swapValue;//在前面已经对判断位赋值了,所以这里仅需要对被交换位赋值就可以啦
        numStr=String.valueOf(numArr);
        return Integer.valueOf(numStr); //转换为整数
        
    }

这里面出现的问题是:不仅要考虑大数往前移,还有考虑小数要往后移,尤其是出现重复数字时,该情况尤为明显,例如:1939,按照刚刚的算法,判断最高位1的时候,就输出交换结果9139,但是如果将1与最后一位9交换可以得到更大值,即:9931。

改进:判断的时候加个等号,这样更新最后的索引就是最后面的索引值了,例如第一次交换后当前位为9,下一次与3判断是大于3的不做处理,下一次与9判断是等于,这时候要更新swapIndex的值,让它为最后一位9的索引值,这样就可以把最小值换到后面。代码如下(结果依旧不对...骂人不对):

public int maximumSwap(int num) {
        if(num<10){
            return num;
        }
        String numStr=num+"";
		char[] numArr=numStr.toCharArray();
        int swapIndex=0;
        char swapValue='a';
        for(int i=0;i<numArr.length;i++){
            swapValue=numArr[i];
            swapIndex=i;
            for(int j=i+1;j<numArr.length;j++){               
                if(numArr[i]<=numArr[j]){
                    numArr[i]=numArr[j];
                    swapIndex=j;
                }
            }
            if(i!=swapIndex){
                break;
            }
        }
        numArr[swapIndex]=swapValue;
        numStr=String.valueOf(numArr);
        return Integer.valueOf(numStr);
        
    }

这时候出现的尬值就是:98368,正常交换后是:98863.然而由于刚刚程序里面加了等号,所以遇见相等的也交换了,直接跳出循环返回结果。这是不对的。所以要对等于的情况进行特殊处理。
加个判断值,判断当前值是否被交换过,如果被交换过,那么等于是有意义的,如果没有被交换过,那么等于就没有任何用。

public int maximumSwap(int num) {
        if(num<10){
            return num;
        }
        String numStr=num+"";
		char[] numArr=numStr.toCharArray();
        int swapIndex=0;
        char swapValue='a';
        boolean isSwap=false;
        for(int i=0;i<numArr.length;i++){
            swapValue=numArr[i];
            swapIndex=i;
            isSwap=false;
            for(int j=i+1;j<numArr.length;j++){               
                if(numArr[i]<numArr[j]){
                    numArr[i]=numArr[j];
                    swapIndex=j;
                    isSwap=true;
                }else if(numArr[i]==numArr[j]){
                    swapIndex=j;
                }
            }
            if((i!=swapIndex)&&isSwap){
                break;
            }
        }
        numArr[swapIndex]=swapValue;
        numStr=String.valueOf(numArr);
        return Integer.valueOf(numStr);
        
    }

终于成功,撒花~

下面再分析一下,LeetCode上的更好的代码:

public int maximumSwap(int num) {
        char[] digits = Integer.toString(num).toCharArray(); //一样转为了字符数组
        int[] buckets = new int[10]; // 桶 值 存储 0-9分别在该数中第几位
        for(int i = 0;i < digits.length;i ++){
            buckets[digits[i] - '0'] = i; //如果是6273的情况 则桶值是 [0,0,1,3,0,0,0,2,0,0]
        }
        for(int i = 0;i < digits.length;i ++){    //从第一位开始判断
            for(int k = 9;k > digits[i] - '0';k --){  //从9开始判断是否比当前位大,如果大则判断在桶值中有没有,如果有则交换当前位与这个值
                if(buckets[k] > i){
                    char temp = digits[i];
                    digits[i] = digits[buckets[k]];
                    digits[buckets[k]] = temp;
                    return Integer.valueOf(new String(digits));
                }
            }
        }
        return num;
    }





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值