【陪伴式刷题】Day 33|贪心算法|738.调递增的数字(Monotone Increasing Digits)

刷题顺序按照代码随想录建议

题目描述

英文版描述

An integer has monotone increasing digits if and only if each pair of adjacent digits x and y satisfy x <= y.

Given an integer n, return the largest number that is less than or equal to n with monotone increasing digits.

Example 1:

Input: n = 10 Output: 9

Example 2:

Input: n = 1234 Output: 1234

Example 3:

Input: n = 332 Output: 299

Constraints:

  • 0 <= n <= 10^9

英文版地址

leetcode.com/problems/mo...

中文版描述

当且仅当每个相邻位数上的数字 x 和 y 满足 x <= y 时,我们称这个整数是单调递增的。

给定一个整数 n ,返回 小于或等于 n 的最大数字,且数字呈 单调递增

示例 1:

输入: n = 10 输出: 9

示例 2:

输入: n = 1234 输出: 1234

示例 3:

输入: n = 332 输出: 299

提示:

  • 0 <= n <= 10^9

中文版地址

leetcode.cn/problems/mo...

解题方法

暴力法

第一反应,就减1减1一直判断呗~(果然超时了(˶‾᷄ ⁻̫ ‾᷅˵),不过方法肯定是对的嘿嘿( ̄∇ ̄))

java 复制代码
class Solution {
    public int monotoneIncreasingDigits(int n) {
        if (n <= 10) {
            return n - 1;
        }
        int result = n;
        while (result > 0) {
            if (isValid(result)) {
                return result;
            }
            result = result - 1;
        }
        return result;
    }

    private boolean isValid(int result) {
        String r = result + "";
        int cur = 0;
        for (int i = 0; i < r.length(); i++) {
            char c = r.charAt(i);
            int i1 = Integer.parseInt(c + "");
            if (cur > i1) {
                return false;
            }
            cur = i1;
        }
        return true;
    }
}

复杂度分析

  • 时间复杂度:O(m),m表示数字 n 的位数,但是这个结果不确定(欢迎批评指正~~),因为没算isValid()方法中的for循环,这个for循环的时间复杂度取决于整数的位数
  • 空间复杂度:O(1)

贪心法

暴力解法优化后

java 复制代码
class Solution {
     public int monotoneIncreasingDigits(int n) {
        int result = n;
        if (result < 10) {
            return result;
        }
        if (result < 100) {
            int unit = result % 10;
            int decade = result / 10;
            if (decade > unit) {
                return (decade - 1) * 10 + 9;
            } else {
                return result;
            }
        }
        String ns = n + "";
        char[] charsN = ns.toCharArray();
        int index = charsN.length;
        // 332
        for (int i = charsN.length - 1; i > 0; i--) {
            int ci = Integer.parseInt(charsN[i] + "");
            int prei = Integer.parseInt(charsN[i - 1] + "");
            if (prei > ci) {
                charsN[i - 1]--;
                index = i;
            }
        }
        for (int i = 0; i < charsN.length; i++) {
            if (i >= index) {
                charsN[i] = '9';
            }
        }
        result = Integer.parseInt(String.valueOf(charsN));
        return result;
    }
}

复杂度分析

  • 时间复杂度:O(m),m表示数字 n 的位数
  • 空间复杂度:O(m),额外的chars[]占用空间

字符串版

java 复制代码
class Solution {
    public int monotoneIncreasingDigits(int N) {
        String[] strings = (N + "").split("");
        int start = strings.length;
        for (int i = strings.length - 1; i > 0; i--) {
            if (Integer.parseInt(strings[i]) < Integer.parseInt(strings[i - 1])) {
                strings[i - 1] = (Integer.parseInt(strings[i - 1]) - 1) + "";
                start = i;
            }
        }
        for (int i = start; i < strings.length; i++) {
            strings[i] = "9";
        }
        return Integer.parseInt(String.join("",strings));
    }
}

这里用到了Integer.parseInt(String.join("",strings))来合并字符串数组并转化为数字,不过整个代码多次使用Integer.parseInt()方法,这导致不管是耗时还是空间占用都非常高,后面有数组优化版

复杂度分析

  • 时间复杂度:O(m),m表示数字 n 的位数
  • 空间复杂度:O(m),额外的string[]占用空间

数组优化版

java 复制代码
class Solution {
    public int monotoneIncreasingDigits(int n) {
        String s = String.valueOf(n);
        char[] chars = s.toCharArray();
        int start = s.length();
        for (int i = s.length() - 2; i >= 0; i--) {
            if (chars[i] > chars[i + 1]) {
                chars[i]--;
                start = i+1;
            }
        }
        for (int i = start; i < s.length(); i++) {
            chars[i] = '9';
        }
        return Integer.parseInt(String.valueOf(chars));
    }
}

可以看到优化效果很明显,这个其实跟我的第一版思路和方式都一样,不过相比我的那版对于1位和2位的整数做单独处理,这个代码兼容了各个位数的整数,此外有几点很实用的操作:

  • chars[i]--:如果chars[]可以直接使用--来操作
  • Integer.parseInt(String.valueOf(chars)):跟上面的Integer.parseInt(String.join("",strings))类似,这段代码可以把chars[]里所有的数字连起来,然后转换成一个数字

复杂度分析

  • 时间复杂度:O(m),m表示数字 n 的位数
  • 空间复杂度:O(m),额外的chars[]占用空间
相关推荐
Seven974 分钟前
线性数据结构
java
带刺的坐椅7 分钟前
Solon 不依赖 Java EE 是其最有价值的设计!
java·spring·web·solon·javaee
青云交10 分钟前
Java 大视界 -- 基于 Java 的大数据分布式存储在数字媒体内容存储与版权保护中的应用
java·性能优化·区块链·分布式存储·版权保护·数字媒体·ai 识别
踢球的打工仔27 分钟前
PHP面向对象(5)
android·java·php
Rover.x29 分钟前
错误:找不到或无法加载主类 @C:\Users\AppData\Local\Temp\idea_arg_file223456232
java·ide·intellij-idea
4***172731 分钟前
使用 java -jar 命令启动 Spring Boot 应用时,指定特定的配置文件的几种实现方式
java·spring boot·jar
czlczl200209251 小时前
算法:组合问题
算法·leetcode·职场和发展
CoderYanger1 小时前
优选算法-字符串:63.二进制求和
java·开发语言·算法·leetcode·职场和发展·1024程序员节
3***31211 小时前
java进阶1——JVM
java·开发语言·jvm
Cx330❀1 小时前
C++ STL set 完全指南:从基础用法到实战技巧
开发语言·数据结构·c++·算法·leetcode·面试