leetcode
leetcode 601 ~ 650
单调递增的数字

单调递增的数字

难度:

标签:

题目描述

代码结果

运行时间: 21 ms, 内存: 16.0 MB


/*
 * 题目思路:
 * 1. 使用Stream对字符串进行处理。
 * 2. 将数字转换为字符数组,以便逐个检查每一位。
 * 3. 从左到右扫描字符数组,找到第一个违反单调递增的地方。
 * 4. 将该位减1,并将其右侧的所有位变为9。
 */
import java.util.stream.IntStream;

public class MonotoneIncreasingDigitsStream {
    public int monotoneIncreasingDigits(int n) {
        char[] digits = Integer.toString(n).toCharArray();
        int marker = IntStream.range(1, digits.length)
            .filter(i -> digits[i] < digits[i - 1])
            .findFirst()
            .orElse(digits.length) - 1;
        if (marker >= 0) digits[marker]--;
        IntStream.range(marker + 1, digits.length).forEach(i -> digits[i] = '9');
        return Integer.parseInt(new String(digits));
    }
}

解释

方法:

这个题解的思路是从数字的末尾开始,逐位进行分析。如果当前位的数字比前一位的数字小,那么就将前一位的数字减1,并将当前位以及后面的所有位都设置为9。这样可以确保修改后的数字是小于等于原数字的最大单调递增数字。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
为什么在发现当前位的数字比前一位的数字小时,将前一位的数字减1而不是进行其他操作?
当一位数字比前一位小时,说明从这个位置开始无法维持数字的单调递增。直接减小前一位的数字并将后面的数字全部改为最大可能值(9)是为了确保在保持数值尽可能大的同时,修改后的数仍然满足单调递增的条件。如果不减小前一位而是采用其他操作,可能会使得最终的数值更小,或者逻辑更加复杂且难以实现。
🦆
在处理过程中,将当前位以及后续所有位设置为9的操作是如何保证结果是小于等于原数字的最大单调递增数字?
将当前位及之后的所有位设置为9,是因为一旦减小了前一位,那么后面的位设置为最大值9可以使得修改后的数字尽可能大。由于前一位已经减小,即使后续位全为9,整个数字也保证是小于原始数字的。这样操作确保了结果既是单调递增的,又是小于原数字的最大可能值。
🦆
如果在数字的最高位需要进行修改,这种方法处理后的结果是否依然有效?
如果最高位也需要减小,该策略依然有效。即使是最高位减1,其后所有位设为9仍然会形成一个小于原始数字且尽可能大的单调递增数字。例如从2803减小到2799,尽管2803的最高位2未改变,但类似地,从9200减小到8999也是有效的,即使最高位9变成了8。
🦆
在将字符列表重新转换成整数时,是否有可能遇到整数溢出的问题,尤其是在接近输入范围上限的情况下?
在Python中,整数类型(int)是动态的,可以处理非常大的数字而不会像其他一些语言那样遇到整数溢出的问题。因此,在使用Python处理这类问题时,通常不需要担心整数溢出的问题,除非数字超出了语言处理的范围,这在实际情况中极为罕见。

相关问题

移掉 K 位数字

给你一个以字符串表示的非负整数 num 和一个整数 k ,移除这个数中的 k 位数字,使得剩下的数字最小。请你以字符串形式返回这个最小的数字。

 

示例 1 :

输入:num = "1432219", k = 3
输出:"1219"
解释:移除掉三个数字 4, 3, 和 2 形成一个新的最小的数字 1219 。

示例 2 :

输入:num = "10200", k = 1
输出:"200"
解释:移掉首位的 1 剩下的数字为 200. 注意输出不能有任何前导零。

示例 3 :

输入:num = "10", k = 2
输出:"0"
解释:从原数字移除所有的数字,剩余为空就是 0 。

 

提示:

  • 1 <= k <= num.length <= 105
  • num 仅由若干位数字(0 - 9)组成
  • 除了 0 本身之外,num 不含任何前导零