Skip to content
本页目录

0738-单调递增的数字

https://leetcode.cn/problems/monotone-increasing-digits

当且仅当每个相邻位数上的数字 x 和 y 满足 x <= y 时,我们称这个整数是单调递增的。 给定一个整数 n ,返回 小于或等于 n 的最大数字,且数字呈 单调递增 。

示例 1:

输入: n = 10
输出: 9

示例 2:

输入: n = 1234
输出: 1234

示例 3:

输入: n = 332
输出: 299

提示:

  • 0 <= n <= 10^9

思路:有问题

考虑 :1 位数,就等于他自己 考虑 : 2 位数,原来就是递增的就是他自己,如果是递减的,就是前一个数减1,后一个数变成9 考虑 : 3 位数,两位数-1,然后最后加9

从后往前计算有问题,比如 328 会求出 298 而不是 299

需要从前往后计算,如何知道第一位的数字?

参考代码

csharp
public class Solution {
    public int MonotoneIncreasingDigits(int n) {
    	if(n == 0){
    		return 0;
    	}
    	int lastDigit = n % 10;
    	int lastSecondDigit = n / 10 % 10;
    	int result;
    	if(lastDigit >= lastDigit){
    		result = MonotoneIncreasingDigits(n / 10) * 10 + lastDigit;
    	}
    	else{
    		result = MonotoneIncreasingDigits( n / 10 - 1) * 10 + 9;
    	}

    	return result;
    }
}

思路2:从前往后贪心计算

要尽可能的大,那么这个数从高位开始要尽可能地保持不变。那么我们找到从高到低第一个满足 str[i] > str[i+1] 的位置,然后把 str[i] - 1,再把后面的位置都变成 99 即可。对应可看下面的例子。

参考代码:转字符串

csharp
public class Solution{
	public int MonotoneIncreasingDigits(int n){
		char[] arr = n.ToString().ToCharArray();
		int i=1;
		//找出非递增的位置
		while(i < arr.Length){
			if(arr[i-1] <= arr[i]){
				i++;
			}
            else{
                break;
            }
		}
		//开始扣减前一位
		if(i<arr.Length){
			
			while(i>0 && arr[i-1] > arr[i]){
				arr[i-1]--;
				i--;
			}
			
			for(int index = i+1; index < arr.Length; index++){
				arr[index] = '9';
			}
		}

		return Convert.ToInt32(new string(arr));
	}
}

思路3:贪心优化查找 【巧妙】

在上一个思路中,当发现下一个数小于上一个数字的时候,我们把上个数字的数值-1,此时需要多考虑当-1之后,是否比以前小的情况。 这种情况,只有前两个数相同的时候才会发生,比如 33, 变成 32 , 所以我们找到一个确切递增的max值,我们记录下来的索引就是需要更新的记录。
因为他比前面的数至少大于1 https://leetcode.cn/problems/monotone-increasing-digits/solution/jian-dan-tan-xin-shou-ba-shou-jiao-xue-k-a0mp/

csharp
public class Solution{
	public int MonotoneIncreasingDigits(int n){
		char[] arr = n.ToString().ToCharArray();
		int max = -1;
		int index = -1;

		for(int i=0; i<arr.Length; i++){
			if(arr[i] > max){
				max = arr[i];
				index = i;
			}
			if(i>0 && arr[i] < arr[i-1]){
				arr[index]--;
				//更新后面的9
				for(int j=index+1;j<arr.Length;j++){
					arr[j] = '9';
				}
				break;
			}
		}

		return Convert.ToInt32(new string(arr));
	}
}

复习 20220513

csharp
public class Solution {
    public int MonotoneIncreasingDigits(int n) {
        char[] arr = n.ToString().ToCharArray();
        int max = -1;
        int index = -1;
        for(int i=0; i<arr.Length; i++){
            if(arr[i] > max){ //从前往后找到最大的数
                max = arr[i];
                index = i;
            }
            //判断后面是否开始递减了
            if(i>0 && arr[i] < arr[i-1]){
                arr[index]--;
                for(int j=index+1; j<arr.Length;j++){
                    arr[j] = '9';
                }
                break; //退出循环
            }
        }
        //输出
        int result = 0;
        for(int i=0; i<arr.Length; i++){
            result = result * 10 + (arr[i] - '0');
        }
        return result;
    }
}

复习:20220320

注意要找到两个数,一个是严格递增的数,从这个数开始扣减1. 另外一个数是开始递减的数。 如果发现了这个数,说明需要开始处理。

如果每个数字都不相同,那么问题就简化为,找到递减的数,他前面的数字扣减1,后面都变成9就可以了, 比如 12321 就变成12299

但时当前面数字有相等的时候,比如 123321 此时我们不能直接扣减第二个3,这样结果就是 123299 出现递减了,所以我们要找到相等的第一个数。

所以从开始,我们可以记录严格递增的那个数,就是开始需要扣减的那个数,比如 123321 一直到第一个3都是严格递增的,所以记录 left = 2

然后我们记录后面是否有递减(nums[i] < nums[i-1]),是的话,就从 left 开始扣减

从严格递增的数字开始,扣减1,然后后面都变成99

csharp
public class Solution {
    public int MonotoneIncreasingDigits(int n) {
        int left = 0;
        char[] strs = n.ToString().ToArray();
        for(int i=1; i<strs.Length; i++){
            if(strs[i] > strs[left]){ //找到严格递增的位置
                left = i;
            }
            else if(strs[i] < strs[i-1]){ //如果发现有递减,说明需要处理,从严格递增的位置开始扣减
                strs[left]--;
                for(int j=left+1; j<strs.Length; j++){
                    strs[j] = '9';
                }
                break;
            }
        }        
        string s= new string(strs);
        return Convert.ToInt32(s);
    }
}

Released under the MIT License.