算法练习帖--29--单调递增的数字(Java)

单调递增的数字

一、题目描述

给定一个非负整数 N,找出小于或等于 N 的最大的整数,同时这个整数需要满足其各个位数上的数字是单调递增。

(当且仅当每个相邻位数上的数字 x 和 y 满足 x <= y 时,我们称这个整数是单调递增的。)
(题目来源:力扣(LeetCode))

示例 1:
输入: N = 10
输出: 9
示例 2:
输入: N = 1234
输出: 1234
示例 3:
输入: N = 332
输出: 299

二、解决方法

1. 逻辑法(看完官方题解的我,眼泪掉下来)
取到正整数N的位数,从高位向低位遍历,找到"下坡点",本来要正序,要是没有逆序的两个数字说明正整数N符合要求,如果有两个数字逆序,按顺序称为B,C
即B>C,再找到B之前的数字A,此时有两种情况:
1.若A不存在(B已经是最高位),B变为B-1,C变为9
2. 若A存在(也有两种情况):

  • 若B>A,B变为B-1,C变为9
  • 若B<=A,A变为A-1,B和C都变为9
    在这里插入图片描述
package com.lxf.test;

public class MonotoneIncreasingDigits {
    
    
	public static void main(String[] args) {
    
    
		//1-9 1-9
		// 10  9
		// 22 22
		// 15 15
		// 76 69
		// 45 45
		//131 129
		//110 99
		//210 199
		//1101 999
		//3433 3399
		//3354 3349
		//332 299
		System.out.println(monotoneIncreasingDigits(10));
	}
   public static int monotoneIncreasingDigits(int N) {
    
    
		//获取正整数N最大的位数maxDigital
	   int maxDigital=1;
	   int m=N;
	   //获取当前位数字的基数(用于截取数字)
	   int base=1;
	   while(m/10!=0) {
    
    
		   maxDigital++;
		   m/=10;
		   base*=10;
	   }
	   //循环位数
	   int i=maxDigital;
	   //获取第一位上的数字
	   int first,second;
	   second=N/base;
	   while(i>1) {
    
    
	   		//从高位第一位开始往下搜索(第二次直接拿second就好)
		   first=second;
		   //从高位第二位开始往下搜索
		   if(i!=2) {
    
    
			   second=(N%base)/(base/10);
		   }else {
    
    
			   second=N%10;
		   }
		   //当前位数字大于下一位数字开始处理
		   if(first>second) {
    
    
		   	   //获取base2,当前前一位数的基数
			   int base2=base*10;
			   int j=i+1;
			   while(j<=maxDigital) {
    
    
			   	   //first的前一位
			   	   int zero=0;
			   	   //最高位上的数和其它位上的数计算方式不一样
				   if(j==maxDigital) {
    
    
					   zero=N/base2;
				   }else {
    
    
					   zero=N%(base2*10)/base2;
				   }
				   //如果zero为最高位,并且最高位和下一位相等直接返回结果就好
				   if(j==maxDigital&&zero==first) {
    
    
					   return (N/base2)*base2-1;
				   }
				   //如果first大于zero,说明first可减去1,first后的全置为9(最大)
				   if(first>zero) {
    
    
					   return N-N%(base2/10)-1;
				   }
				   first=zero;
				   j++;
				   base2*=10;
			   }
			   return (N/base)*base-1;
		   }
		   i--;
		   base/=10;
	   }
	   return N;
   }
}

2. 贪心法(官方题解,想法一样,实现不一样)

class Solution {
    
    
    public int monotoneIncreasingDigits(int N) {
    
    
        char[] strN = Integer.toString(N).toCharArray();
        int i = 1;
        //从高位向低位寻找高位数字大于高位下一位的数字
        while (i < strN.length && strN[i - 1] <= strN[i]) {
    
    
            i += 1;
        }
        //如果这个数字小于strN的长度就处理
        if (i < strN.length) {
    
    
        	//从这个位置开始减1,如果减完1大于等于这个位置前一位的数字就不必要继续
        	//否则这个位置的前一位持续减一
        	//比如332  第二位大于第三位,首先第二位减一等于2小于第一位,
        	//所以第一位还要减去1,等于222进入下一步处理
            while (i > 0 && strN[i - 1] > strN[i]) {
    
    
                strN[i - 1] -= 1;
                i -= 1;
            }
            //将最后一次减1的位数字后面所有数字都置为9
            //222->299
            //如果
            for (i += 1; i < strN.length; ++i) {
    
    
                strN[i] = '9';
            }
        }
        return Integer.parseInt(new String(strN));
    }
}

猜你喜欢

转载自blog.csdn.net/Inmaturity_7/article/details/111239786