前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >leetcode每日一题:738. 单调递增的数字

leetcode每日一题:738. 单调递增的数字

作者头像
用户7685359
发布于 2020-12-22 07:36:52
发布于 2020-12-22 07:36:52
73500
代码可运行
举报
文章被收录于专栏:FluentStudyFluentStudy
运行总次数:0
代码可运行

leetcode每日一题:738. 单调递增的数字:https://leetcode-cn.com/problems/monotone-increasing-digits/

一起刷题吧

一、题意分析

输入:非负整数(大于等于0) 输出:比输入小或等的,且对于这个数值,从左到右,呈单调递增(包括等) 难度:中等 标签:贪心

示例 1: 输入: N = 10 输出: 9

示例 2: 输入: N = 1234 输出: 1234

示例 3: 输入: N = 332 输出: 299

二、参考代码

这个题目,个人认为是一个数学题目,可以通过数学思维来解决。要想数值最大且满足题目要求,则需要在高位尽可能不变,低位最大的情况下去做转变,低位最大显然就是变成 9,而此时相应的高位需要减小。这里以几个特殊数值为例说明这个过程:

示例一:N = 332

  1. 个位数:2,符合题目要求,继续向前遍历,N = 33
  2. 个位数:3,3 > 2,不符合题目要求,这个时候需要做变化。秉承低位最大的原则,原来的 2 应该变为 9,高位尽可能不变,但此时需要变化,那想要最大,则应该变为比它小的最大的一个数值,当前高数是 3,比它小的最大一个数值显然是 2,因此此时值为 29, N = 3
  3. 个位数为3,此时不符合题目要求,按同样的标准做替换,值为 299 此时 N = 0,结束循环,因此最终结果为 299

示例二:N = 4332

  1. 个位数:2,符合要求,N = 433
  2. 个位娄:3,不符合要求,转换结果为 29,N = 43
  3. 个位数:3,不符合要求,转换结果为 299,N = 4
  4. 个位数:4,不符合要求,转换结果为 3999, N = 0

示例三:N = 45443

  1. 个位数:3,符合要求,N = 4544
  2. 个位数:4,不符合要求,转换结果为 39, N = 454
  3. 个位数:4,不符合要求,转换结果为 399,N = 45
  4. 个位数:5,不符合要求,转换结果为 4999,N = 4
  5. 个位数:4,符合要求,结果为 44999,N = 0

同样的推理,大家可以试下:N = 4332 以及 N = 4321 这两组数据。通过观察,我们可以发现如果新的个位数与它前一位比较,如果符合题目中的递增要求,则直接写入在最前位即可,如果不符合,则需要做转换,转换的规律也很简单,即将原来记录的结果每一位都转换为 9,即低位最大,而当前获取的个位数减 1 之后,写入在记录的最前位即可。

通过上面的推导过程,我们知道需要记录前一位被比较的数值,同时还涉及到低位替换为 9 的过程,我们可以在遍历的过程把低位替换 9 的结果保存下来,在需要替换时直接取值即可,参考代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution:
    def monotoneIncreasingDigits(self, N: int) -> int:
        if N <= 0:
            return N

        # 前一个被比较值
        p = N % 10
        # 最后返回的结果值
        result = p
        # 相当于记录位数
        mul = 10
        # 记录将每一位替换为 9 之后的结果,方便替换时直接取值
        nine = 9
        # N 值向后移
        N = N // 10
        while N:
            r = N % 10
            if r > p:
                # 当前位变成p,已经经过的位都变成9
                result = nine + mul * (r - 1)
                p = r - 1
            else:
                result = result + mul * r
                p = r
            N = N // 10
            nine = nine + 9 * mul
            mul = mul * 10
        return result

执行情况:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
执行用时:44 ms, 在所有 Python3 提交中击败了 40.91% 的用户
内存消耗:14.7 MB, 在所有 Python3 提交中击败了 5.70% 的用户

能过,但执行速度上并不是最优的。这里我们重新审视一下整个过程,可以发现这个从后往前遍历里有很多重复的转换过程,高位做了转换相当于低位做了转换,那我们是否可以从前往后遍历呢?显然也是可以的。

从前往后遍历的思路也很简单,遍历找到第一个不满足递增条件的位置,将此位置减 1,此位置之后的数值全变成 9 即可。但需要注意的是,因为涉及到有一个位置会减 1,所以可能出现减 1 之后,与前一位不再是递增关系了,因此当我们找到了第一个不满足递增条件的位置后,要从当前位置往前找,找到第一个满足减 1 之后仍然满足递增条件位置。也就是说两个寻找:

  1. 从前往后找到第一个不满足递增条件的位置
  2. 从后往前找到第一个满足减 1 后仍然满足递增条件的位置
  3. 找到位置之后的元素变成 9,当前位置减 1,就是最终结果

实现参考代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution:
    def monotoneIncreasingDigits(self, N: int) -> int:
        if N <= 0:
            return N

        N = list(str(N))
        i = 1
        # 记录最后一个满足减一之后仍然符合递增条件的位置
        pos = 0
        while i < len(N) and N[i] >= N[i - 1]:
            if N[i] > N[i - 1]:
                pos = i
            i += 1
        if i < len(N):
            inv = int(N[i])
            if inv - 1 < int(N[i - 1]):
                i = pos
            N[i] = str(int(N[i]) - 1)
            for j in range(i + 1, len(N)):
                N[j] = '9'
        return int("".join(N))

这次提交后时间上击败了 88% 的用户,看了下提交里超过 100% 的用户代码,提交了下,运行和上面代码是一样的。不过那个代码的思路也比较有意思,这里贴上代码(因为从提交中找到的,没有来源可标注):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution_others:
    def monotoneIncreasingDigits(self, N: int) -> int:
        digits = []
        if N == 0:
            return 0
        while N:
            digits.append(N % 10)
            N //= 10
        digits = digits[::-1]

        marker = len(digits)  # marker是第一个需要改成9的数字
        for i in range(len(digits) - 1, 0, -1):  # 从低位到高位遍历

            if digits[i - 1] > digits[i]:
                digits[i - 1] -= 1  # 只减1,给前面的数留下更多空间,后面的数都会改成9的
                marker = i

        for i in range(marker, len(digits)):
            digits[i] = 9

        res = 0
        for i in range(len(digits)):
            res = res * 10 + digits[i]
        return res

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-12-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FluentStudy 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
leetcode每日一题:738. 单调递增的数字
题目:https://leetcode-cn.com/problems/monotone-increasing-digits
用户3578099
2020/12/30
4320
LeetCode 738. Monotone Increasing Digits
这是我开始选择的方法,非常直白,但是直白简单的方法往往不是最佳的解法,提交到LeetCode上,给我抛出一个超时,可见效率有多低。首先写一个函数,判断一个数是否是符合要求的,如果不符合要求,就将这个数递减,直到找到符合的数为止,试想假如这个数是95555555555,那么符合题意的数是9,想想看要做多少次减法啊!!!!
大学里的混子
2018/10/24
7450
单调递增的数字
给定一个非负整数N,找出小于或等于N的最大的整数,同时这个整数需要满足其各个位数上的数字是单调递增。当且仅当每个相邻位数上的数字x和y满足x <= y时,我们称这个整数是单调递增的。
WindRunnerMax
2020/12/18
1.5K0
LeetCode 738. 单调递增的数字(贪心)
给定一个非负整数 N,找出小于或等于 N 的最大的整数,同时这个整数需要满足其各个位数上的数字是单调递增。
Michael阿明
2020/07/13
9640
LeetCode 738. 单调递增的数字(贪心)
【一天一大 lee】单调递增的数字 (难度:中等) - Day20201215
给定一个非负整数 N,找出小于或等于 N 的最大的整数,同时这个整数需要满足其各个位数上的数字是单调递增。
前端小书童
2020/12/17
5730
贪心算法:单调递增的数字
给定一个非负整数 N,找出小于或等于 N 的最大的整数,同时这个整数需要满足其各个位数上的数字是单调递增。
代码随想录
2020/12/29
7280
【Day23】力扣:LeetCode算法刷题 [927. 三等分 ] [415. 字符串相加]
如果无法做到,就返回 [-1, -1]。 注意,在考虑每个部分所表示的二进制时,应当将其看作一个整体。例如,[1,1,0] 表示十进制中的 6,而不会是 3。此外,前导零也是被允许的,所以 [0,1,1] 和 [1,1] 表示相同的值。 / 示例 1: 输入:arr = [1,0,1,0,1] 输出:[0,3] / 示例 2: 输入:arr = [1,1,0,1,1] 输出:[-1,-1] / 示例 3: 输入:arr = [1,1,0,0,1] 输出:[0,2] / 提示: 3 <= arr.length <= 3 * 104 arr[i] 是 0 或 1
.29.
2022/11/15
2580
【Day23】力扣:LeetCode算法刷题 [927. 三等分 ] [415. 字符串相加]
Leetcode|中等|序列|738. 单调递增的数字
贪心算法 【考核知识】从任意数的十位至更高位,如何读取每个数 class Solution { public: int monotoneIncreasingDigits(int N) { if (N < 10) return N; int k; // 从十位开始向更高位遍历 for (k = 10; N / k > 0; k *= 10) { // 高位比低位数值大 if (N / k
SL_World
2021/09/18
6520
LWC 61:738. Monotone Increasing Digits
该文讲述了如何利用单调栈实现一个高效的算法,求解输入整数N的最大单调递增数字。该算法的时间复杂度为O(n),其中n是输入整数N的位数。该算法利用了单调栈的特性:当从左到右扫描数组时,如果栈顶元素等于当前遍历的元素,那么栈顶元素会保持不变;否则,栈顶元素会一直单调递减。因此,该算法只需要从左到右扫描一遍数组,即可找到最大的单调递增数字,并将其作为结果返回。
用户1147447
2018/01/02
5510
【每日一题】【leetcode】3. 数组-加一
给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。 最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。 你可以假设除了整数 0 之外,这个整数不会以零开头。 难易程度:easy 示例 1: 输入: [1,2,3] 输出: [1,2,4] 解释: 输入数组表示数字 123。
aneutron
2022/08/10
1900
【Leetcode -500.键盘行 -504.七进制数】
题目:给你一个字符串数组 words ,只返回可以使用在 美式键盘 同一行的字母打印出来的单词。
YoungMLet
2024/03/01
1280
文心一言 VS 讯飞星火 VS chatgpt (235)-- 算法导论17.2 3题
为了实现这样一个计数器,我们可以使用一个位数组(bit array)来存储计数器的当前值,并维护一个额外的指针来指向最高位的 1。每次执行 INCREMENT 或 RESET 操作时,我们可以利用这个指针来高效地更新计数器。
福大大架构师每日一题
2024/04/13
1460
文心一言 VS 讯飞星火 VS chatgpt (235)-- 算法导论17.2 3题
LeetCode笔记:66. Plus One
但看题目还看不懂是什么意思,跑了几个测试用例后看答案看明白了,就是数组的每一个位置代表一个数的每一位,有个位十位百位等,如[8]表示数字8,[1,2]表示数字12等等,题目要求将给出的数字代表的数字加一并用同样的形式返回结果。
Cloudox
2021/11/23
1600
刷leetcode系列之数字中的1
暴力法的思想很简单,该精简版为我自己写的,思路是直接循环一次,然后将循环的所有数字先转为字符串,然后转为list,使用list的count方法统计1的个数,累加求和即可实现。
公众号guangcity
2019/09/20
3380
镜像反转重新定义动态规划转移方程--格雷编码|Java 刷题打卡
Gn0+Cn1+Cn2+⋯+Cn1G_{n}^{0}+C_{n}^{1}+C_{n}^{2}+\cdots+C_{n}^{1}Gn0+Cn1+Cn2+⋯+Cn1
啵啵肠
2023/11/29
1540
【Day16】Java算法刷题 [299. 猜数字游戏 ] [1.两数之和] [面试题 01.09. 字符串轮转 ]
解题思路: 题目中给到我们两串数字,一串是secret 另外一串是 guess,分别是游戏的答案 与 参与者猜测的答案。 简单总结一下游戏规则,当我们猜的一串数字中,撞到了答案中某个出现的数字时,有两种情况:
.29.
2022/11/15
3260
【Day16】Java算法刷题 [299. 猜数字游戏 ] [1.两数之和] [面试题 01.09. 字符串轮转 ]
【甘泉算法】一文搞定单调栈问题
本文主要利用单调栈来解决leetcode上的典型问题,其实它的应用范围倒是不广,主要解决的都是类似于leetcode上下一个更大元素的问题,本文将从这类问题出发,帮助大家掌握单调栈的应用技巧。主要题型如下所示:
itlemon
2022/01/10
8230
【甘泉算法】一文搞定单调栈问题
PAT 1023 Have Fun with Numbers (20分) 字符数组解决大整数存储溢出
Notice that the number 123456789 is a 9-digit number consisting exactly the numbers from 1 to 9, with no duplication. Double it we will obtain 246913578, which happens to be another 9-digit number consisting exactly the numbers from 1 to 9, only in a different permutation. Check to see the result if we double it again!
vivi
2020/07/14
4280
LeetCode | 66.加一
这道题目的思路比较符合我们平时列竖式的思路,这道题目我使用 C 语言进行完成,看我下面的分析。
码农UP2U
2020/09/29
3700
LeetCode | 66.加一
每日一题:LeetCode-611. 有效三角形的个数
   🔎🔎如果说代码有灵魂,那么它的灵魂一定是👉👉算法👈👈,因此,想要写出💚优美的程序💚,核心算法是必不可少的,少年,你渴望力量吗😆😆,想掌握程序的灵魂吗❓❗️那么就必须踏上这样一条漫长的道路🏇🏇,我们要做的,就是斩妖除魔💥💥,打怪升级!💪💪当然切记不可😈走火入魔😈,每日打怪,拾取经验,终能成圣🙏🙏!开启我们今天的斩妖之旅吧!✈️✈️
用户11029129
2024/06/04
780
每日一题:LeetCode-611. 有效三角形的个数
推荐阅读
相关推荐
leetcode每日一题:738. 单调递增的数字
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验