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

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

作者头像
用户7685359
发布于 2020-12-22 07:36:52
发布于 2020-12-22 07:36:52
75600
代码可运行
举报
文章被收录于专栏: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 删除。

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
前端学习(6)~html回顾
html 的常见元素主要分为两类:head 区域的元素、body 区域的元素。下面来分别介绍。
Vincent-yuan
2020/02/23
4730
系统讲解CSS应用
<input type="radio" name="radio1" id="radio1-2" /> <label for="radio1-2">选项二</label> //关联的关键是ID
慕白
2018/08/03
5760
系统讲解CSS应用
前端面试宝典(一)
Hello大家好,兔妞想着咱们分享也有好多了,而且新一轮的秋招又快到了,要不咱收集收集题目,也好自己查缺补漏一下吧~所以最近会有一些面试题目分享给大家,答案也会一并送出哦。但是穿插这中间还是会有干货的分享哟。
萌兔IT
2019/08/05
7260
知识整理之HTML篇
HTML5 不基于 SGML,因此不需要对DTD进行引用,但是需要doctype来规范浏览器的行为(让浏览器按照它们该有的方式来运行) 而HTML4.01基于SGML,所以需要对DTD进行引用,才能告知浏览器文档所使用的文档类型。
Clearlove
2019/08/29
1.3K0
前端基础(HTML,CSS,JavaScript)知识笔记,附:前端基础面试题!!
<form></form> 表单是可以把浏览者输入的数据传送到服务器端,这样服务器端程序就可以处理表单传过来的数据。
全栈程序员站长
2022/07/02
2.5K0
前端基础(HTML,CSS,JavaScript)知识笔记,附:前端基础面试题!!
第2天:HTML常用标签
一、超链接a href:www.baidu.com(跳转页面);id名(锚点跳到相应div位置);01.rar(压缩包) target:_blank(新窗口打开);_self(当前窗口打开) 二、文件路径 绝对路径: (1)线上:线上绝对路径 (2)线下:完整路径
半指温柔乐
2018/09/11
1.2K0
第2天:HTML常用标签
HTML基础
HTML(HyperText Markup Language, 超文本标记语言),用于构建网页基本结构及其内容的标记语言
赤蓝紫
2023/01/01
1.6K0
HTML基础
前端面试题归类-HTML1
比如:header(头部),nav(导航)、section(主要用于对网站或应用程序中页面上的内容进行分块。)、article(一个页面的一部分,并且这部分专门用于独立的分类或复用)、aside(定义article以外的内容,aside的内容应该与article的内容相关。表示当前页 面或文章的附属信息部分)、footer(底部)
肥晨
2023/02/16
5010
HTML基础
一 html html结构 !DOCTYPE html> 告诉浏览器使用什么样的html或者xhtml来解析html文档 <html></html>是文档的开始标记和结束标记。此元素告诉浏览器其自身是
用户1214487
2018/01/24
1.6K0
HTML基础
【HTML5】HTML5 语义化标签 ( HTML5 简介 | 新增特性 | 语义化标签及代码示例 )
HTML5 指的是 对 HTML 语言的第五次重大修改 , 新增了新的元素 / 属性 / 行为 ;
韩曙亮
2023/04/24
2.2K0
【HTML5】HTML5 语义化标签 ( HTML5 简介 | 新增特性 | 语义化标签及代码示例 )
HTML 面试知识点总结
本部分主要是笔者在复习 HTML 相关知识和一些相关面试题时所做的笔记,如果出现错误,希望大家指出!
不愿意做鱼的小鲸鱼
2022/09/26
2K0
HTML 面试知识点总结
献给前端的小伙伴,祝大家面试顺利!
HTML相关问题 1.XHTML和HTML有什么区别 HTML是一种基本的WEB网页设计语言,XHTML是一个基于XML的置标语言 最主要的不同: XHTML 元素必须被正确地嵌套。 XHTML
用户1667431
2018/04/18
1.2K0
前端硬核面试专题之 HTML 24 问
确保用户在不同地区能用最快的速度打开网站,其中某个域名崩溃用户也能通过其他域名访问网站。
夜尽天明
2019/08/08
1.2K0
前端硬核面试专题之 HTML 24 问
HTML基础
HTML基础 ---- HTML基本知识与结构 HTML常见标签 标签写法与嵌套的讨论 HTML、CSS、javascript三者的关系 HTML是网页内容的载体。内容就是网页制作者放在页面上想要让用户浏览的信息,可以包含文字、图片、视频等。 CSS样式是表现。就像网页的外衣。比如,标题字体、颜色变化,或为标题加入背景图片、边框等。所有这些用来改变内容外观的东西称之为表现。 JavaScript是用来实现网页上的特效效果。如:鼠标滑过弹出下拉菜单。或鼠标滑过表格的背景颜色改变。还有焦点新闻(新闻图片)的
用户1667431
2018/04/18
4K0
HTML基础
前端面试那些坑之HTML篇
HTML 1、Doctype作用?标准模式与兼容模式各有什么区别? (1)、<!DOCTYPE>声明位于位于HTML文档中的第一行,处于<html> 标签之前。告知浏览器的解析器用什么文档标准解析这
用户1667431
2018/04/18
1.5K0
『知识巩固#1』Html、Css基础整理
Html 标签学习 排版标签 标题 h1、h2、h3、h4、h5、h6只有这六个 段落标签 p标签 段落之间有空隙换行 换行标签 br 空换行 hr 下划线换行 文本格式化标签 根据语境区分 b、strong 加粗 u、ins 下划线 i、em 倾斜 s、del 删除线 媒体标签 图片标签img 属性名、属性值 alt属性值作为替换文本、src属性作为图片链接、title属性在鼠标悬停时显示 width、height 很容易理解,控制图片宽高 路径 相对路径 绝对
客怎眠qvq
2022/11/01
4.1K0
『知识巩固#1』Html、Css基础整理
HTML/CSS面试题(收集)[通俗易懂]
1、目前主流的浏览器以及其内核名有哪些? 点这里查看 2、内元素和块级元素的区别? 行内元素:不会独立出现在一行,单独使用的时候后面不会有换行符的元素。eg:span, strong, img, a 等。这些元素,默认的高宽,总是其内容的高宽。并且,margin和padding值,只有左右有效。 块级元素:独立在一行的元素,他们后面会自动带有换行符。eg:div , p ,form , ul , li , ol , dl 等。它们的出现,往往独自占领一行。在没有设置宽度的情况下,默认宽度总是其父元素的宽度。 行内元素转换成块元素,只要设置其display属性为block即可,display:block; 。块元素转换成行内元素,只要将其display属性设置为inline即可,display:inline;。
全栈程序员站长
2022/08/31
4310
「资深前端工程师总结」前端面试知识点大全——html篇
定时让网页在3秒内跳转到mozilla首页(http-equiv 属性为名称/值对提供了名称。并指示服务器在发送实际的文档之前先在要传送给浏览器的 MIME 文档头部包含名称/值对。)
用户5997198
2019/08/12
2.1K0
「资深前端工程师总结」前端面试知识点大全——html篇
【web前端阶段一】HTML巩固学习(持续更新)
在<head>中加入<style> 添加css样式,如:对齐,大小,高度,宽度,颜色,布局,圆角
天天Lotay
2022/12/01
4.7K0
【web前端阶段一】HTML巩固学习(持续更新)
HTML 基础
超文本标记语言 (HTML, HyperText Markup Language) ,是构成网页的最基础的内容,用来创建并以可视化方式来呈现网页,它确定了一个网页的内容而不是功能
Nian糕
2018/08/21
4K0
HTML 基础
相关推荐
前端学习(6)~html回顾
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验