DAY40:贪心算法(九)单调递增的数字(贪心的思路)

news2024/11/27 16:40:28

文章目录

    • 738.单调递增的数字(暴力解也需要看一下)
      • 暴力解写法
        • 注意:必须引入`isIncreasing`变量的原因
      • 贪心思路
        • 遍历顺序
      • 最开始的写法
        • debug测试:逻辑错误
      • 修改版
        • debug测试
        • int转化为字符串的原因
        • to_string和stoi的用法
      • 总结

738.单调递增的数字(暴力解也需要看一下)

  • 本题暴力解法也需要看一下,虽然暴力解法超时了,但是这种思路是一种很基础的思路,需要了解
  • 数字是没有办法直接采用下标遍历的,如果要for循环遍历每个位置的数字,需要把数字转成字符串string

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

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

示例 1:

输入: n = 10
输出: 9

示例 2:

输入: n = 1234
输出: 1234

示例 3:

输入: n = 332
输出: 299

提示:

  • 0 <= n <= 10^9

暴力解写法

本题题意比较清晰,我们可以首先考虑用暴力来实现一下。也就是给我们一个数值,我们直接从大到小去遍历,并判断每个数值是不是单调递增的。

  • 注意暴力解法不能直接操作i,直接操作i会导致for循环里i–的时候也受到影响!需要用单独的temp来存储i
  • 暴力解法必须需要 bool isIncreasing的原因,是因为while里面break了之后依然会执行外层的for,也就是说会执行for剩下的代码逻辑!我们不能让break出来之后再continue,因此只能加上判断变量,break的情况就判断为false。确定判断为true的时候,才是结束了while循环的时候,此时再返回。
class Solution {
public:
    int monotoneIncreasingDigits(int n) {
        for(int i=n;i>=0;i--){
            int max = INT_MAX;
            int temp=i;
            //定义判断变量
            bool isIncreasing = true;
            while(temp){//只要还有数字
                int ten = temp%10;//先取最后一位
                if(max>=ten)  max=ten;
                else{
                    isIncreasing = false;
                    break;//只要前一位不满足大于等于,就说明不是单调递增,记为false继续遍历下个数
                }
                temp=temp/10;//i减少一位        
            }
            //结束while并且满足true,说明找到了
            if(isIncreasing==true) 
                return i;      
        }
        //最后没找到 return 0
		return 0;
    }
};

注意:必须引入isIncreasing变量的原因

暴力解法里面需要注意,while循环中的break语句被执行时,它会立即终止当前正在进行的while循环,并且控制流将会继续从break语句跳出while之后,后面的for代码开始执行。这就意味着即使temp并不是单调递增的(在这种情况下,while循环会由于break语句而提前结束),for循环之后的代码也会被执行!这就可能导致不正确的结果被返回。

break只是跳出当前的循环,在while里面的时候,跳出的是while而不是最外层的for

为此,引入了isIncreasing变量。只有在temp是单调递增的情况下(while循环正常结束,而不是由于break语句而提前结束),isIncreasing变量才会保持为true,并且正确的结果i会被返回。

这种解法逻辑正确,但是超时了。

在这里插入图片描述
在这里插入图片描述

贪心思路

我们以32来举例。如果两位不符合要求,前一位需要做-1处理这样后一位才有大于前一位的可能

那么前一位-1之后后一位的值应该取最大的,才能让得到的数值最大

因此32的十位-1得到2 个位取最大得到29。也就是说,遍历数字的时候,凡是前面一位>后面一位,都是前面一位做减一,后面一位取最大值(也就是9)

遍历顺序

以332来举例,如果从前往后遍历,遍历到第二个3的时候,就会发现后面的32换成29之后,整体不满足单调递增了

在这里插入图片描述
从前往后处理的话,因为涉及-1操作,所以后面得到的值,有可能比前面的值要小!会导致遍历到后面不满足单调递增!

从后往前遍历的话,就可以考虑到前一位-1,对前面的数字单调递增特性造成的影响

在这里插入图片描述

最开始的写法

  • 后序遍历的原因,是因为涉及到前一位-1,会对单调递增特性有影响
  • 为了方便挨个数字遍历,把int转换成string
class Solution {
public:
    int monotoneIncreasingDigits(int n) {
        string str = to_string(n);
        //转成字符串就是为了方便遍历
        for(int i=str.size()-1;i>0;i--){
            if(str[i-1]<=str[i]) continue;
            //如果出现i-1>i,就把i换成9
            else{
                str[i]='9';
                str[i-1]=str[i-1]-1;//ASCII码-1
            }
        }
        return stoi(str);//string再转成Int
    }
};

debug测试:逻辑错误

上面这段代码提交出现了逻辑错误,因为得到的并不是最大值。

在这里插入图片描述

修改版

本题贪心的策略,是遇到了相邻数字前一位>后一位,那么就让前一位变成前一位-1但是此时后面的所有数字都需要变成9

示例如下:

在这里插入图片描述
比如上面的例子,就必须考虑后面有多个小于前面的数字的情况。

  • 修改版为了让小于情况下后面所有的数字都成为9,需要定义一个变量来控制9的起始位置
class Solution {
public:
    int monotoneIncreasingDigits(int n) {
        string str = to_string(n);
        //flag之后的元素都换成9,初值是不用换的情况
        int flag=str.size();
        //转成字符串就是为了方便遍历
        for(int i=str.size()-1;i>0;i--){
            if(str[i-1]<=str[i]) continue;
            //如果出现i-1>i,就把i换成9
            else{
                flag=i;
                str[i-1]=str[i-1]-1;//ASCII码-1
            }
        }
        cout<<flag<<endl;
        //遍历结束之后flag之后元素都是9
        for(int i=flag;i<str.size();i++){
            str[i]='9';
        }
        return stoi(str);//string再转成Int
    }
};
  • 时间复杂度:O(n),n 为数字长度
  • 空间复杂度:O(n),需要一个字符串,转化为字符串操作更方便

debug测试

在这里插入图片描述
在这里插入图片描述
修改flag初始值后正确。

int转化为字符串的原因

因为本题需要对数字进行遍历,而我们没有直接的方式去获取和操作其特定位置的数字。因此,通常将整数转换为字符串以便于使用下标进行遍历和比较操作。在这种情况下,使用字符串会使操作更加简单直观。

to_string和stoi的用法

我们此处可以查阅c++string的文档:std::basic_string - cppreference.com

在这里插入图片描述
to_string() 是 C++ 标准库中的一个函数,它用于将各种数值类型(包括整数、浮点数等)转换为字符串。例如,to_string(123) 将返回字符串 "123"

stoi() 函数则是 to_string() 的反向操作,用于将字符串转换为整数。例如**,stoi("123") 将返回整数 123**。值得注意的是,stoi() 函数会忽略字符串开头的空格,直到找到第一个非空格字符。如果这个字符是数字或者正负符号,函数会继续读取剩余部分,直到遇到非数字字符或到达字符串的末尾。

总结

本题只要想清楚个例,例如98,一旦出现strNum[i - 1] > strNum[i]的情况(非单调递增),首先想让strNum[i - 1]减一,strNum[i]赋值9,这样这个整数就是89。就可以很自然想到对应的贪心解法了

想到了贪心,还要考虑遍历顺序,只有从后向前遍历才能重复利用上次比较的结果。

最后代码实现的时候,也需要一些技巧,例如用一个flag来标记从哪里开始赋值9。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/724123.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CPCI-QU-216A正交解码计数器卡

CPCI-QU-216A是用于高速正交解码计数器CPCI板卡&#xff0c;包括6个立计数器&#xff0c;支持索引锁存&#xff0c;支持步长比较输出&#xff0c; 6个高速隔离输入&#xff0c;6个高速隔离输出。 l 32位 cPCI接口 l 6通道隔离输入 l 6通道隔离输出&#xff08;默认用于比较值输…

0125 计算机系统概述

目录 1.计算机系统概述 1.1计算机发展历程 1.2计算机系统层次结构 计算机硬件 计算机软件 计算机系统层次结构 计算机系统工作原理 指令执行过程 1.2部分习题 1.3计算机性能指标 计算机主要性能指标 几个专业术语 1.3部分习题 1.计算机系统概述 1.1计算机发展历程…

三星面板产能紧缺?超半数三星电视机采用其他厂商的面板

今年有超过50%的三星电视未使用自家屏幕&#xff0c;而是采用了来自中国厂商的大部分零件。 据韩国媒体《The Elec》报道&#xff0c;超过一半的三星电视机使用了其他厂商的面板。根据三星电子面板库存明细&#xff0c;大部分的面板来自中国的华星光电、惠科、京东方和咸阳彩虹…

小红书数据分析!Citywalk声量大涨,年轻人为何迷恋它?

近来&#xff0c;一种新型旅游形式——citywalk火了。惬意的城市漫游&#xff0c;成为时下年轻人最潮的逛GAI方式。小红书上更是掀起了citywalk游记潮流&#xff0c;人们纷纷在平台分享记录自己的出游感受。citywalk具体怎么玩&#xff1f;哪些人爱玩&#xff1f;通过分析小红书…

我们来谈谈tcp

"让新离开地表&#xff0c;才能找到盘旋爬升的动力。" 一、认识Tcp报头 (1) 协议报头格式 我们先来认识认识tcp协议报头字段。 跟tcp协议字段报头比起来&#xff0c;udp可真是太轻松了。 协议字段作用源/目的端口号从哪里来&#xff0c;到哪里去32位序号/32位确认…

前端vue入门(纯代码)21_vuex

努力不一定成功&#xff0c;但是&#xff0c;不努力一定很轻松&#xff01;&#xff01;&#xff01; 【23.Vuex】 [可以去官网看看Vuex3文档](Vuex 是什么&#xff1f; | Vuex (vuejs.org)) 问题1&#xff1a;Vuex是什么&#xff1f; 【官方理解1】&#xff1a;Vuex 是一个专…

vue中的.env全局配置

关于文件名&#xff1a; .env 全局默认配置文件&#xff0c;不论什么环境都会加载合并 .env.development 开发环境下的配置文件 .env.production 生产环境下的配置文件 .env文件配置&#xff1a; 我这里要讲的env配置是用启动命令启动项目来配置不同的全局变量 我配置了两…

十七、Jenkins(centos7系统)运行python3代码

十七、Jenkins(centos7系统)运行python3代码 source /usr/python/envs/everyday/bin/activate #激活python3 虚拟环境 创建虚拟环境&#xff1a;https://blog.csdn.net/qq_42846555/article/details/131579627 source /usr/python/envs/everyday/bin/activate #激活python3 虚…

自我介绍,千万别来虚的!

大家好&#xff0c;我是鲏。 已经帮小伙伴改了 500 多份简历了&#xff0c;也发现了一些大家写简历时的共性问题。其中让我印象比较深刻的一个点就是 自我介绍 &#xff0c;基本上所有同学的自我介绍都是这么写的&#xff1a; 读这篇文章的朋友们&#xff0c;你是不是也是这么…

困于“耐用焦虑”的绿源,还在歧路徘徊?

老牌两轮电动车品牌绿源上市之旅“多歧路”。 日前&#xff0c;北京市市场监督管理局公布北京市电动自行车产品质量监督抽查结果&#xff0c;绿源两款电动自行车因存在问题被点名&#xff0c;充电器和蓄电池、整车质量、控制系统等不符合标准。 而在此前&#xff0c;绿源还向港…

秒懂算法 | 围棋中的Alpha-Beta剪枝算法

01、Alpha-Beta剪枝算法 极小化极大算法会遍历所有的可能性&#xff0c;但是根据经验可以知道&#xff0c;并不是所有的选项都需要进行深入的考虑&#xff0c;存在着某些明显不利的选项&#xff0c;当出现这种选项时就可以换一种思路进行考虑了。Alpha-Beta剪枝算法的出现正是…

网络投票平台发起投票平台投票吧网络投票平台

小程序投票活动如何做&#xff1f;很多企业在运营当中&#xff0c;都会通过投票活动来进行推广&#xff0c;从而达到吸粉、增加用户粘度等效果。而此类投票活动&#xff0c;通过小程序就可以实现&#xff0c;操作简单。 我们现在要以“青春大不同”为主题进行一次投票活动&…

系统架构设计师-软件工程(3)

一、软件系统建模 1、结构化建模方法 结构化建模方法是以过程为中心的技术&#xff0c;可用于分析一个现有系统以及定义新系统的业务需求。结构化建模方法所绘制的模型称为数据流图&#xff08;DFD&#xff09;。对于流程较为稳定的系统可考虑结构化建模方法。 2、信息工程建模…

linux中的目录文件都是用来做什么的

1、linux目录系列 - /bin、/sbin目录 我们平时使用的一些命令&#xff0c;是以2进制的格式存放在bin目录下面。例如:cat、chmod、chown、cp、date、find、gzip、kill、ln、ls、mount、mv、ping、pwd、rm、su、tar、vi等。/sbin下存放的是超级用户权限的系统指令。主要放置一些系…

Python采集双色球历史开奖信息,看看哪个号中奖概率更大

目录标题 前言知识点:开发环境:基本流程:代码展示尾语 前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 知识点: 爬虫基本流程 requests的使用 动态数据抓包 开发环境: 解释器: python 3.8 编辑器: pycharm 2022.3 requests >>> pip install requests 第三…

Jenkins邮件配置报错com.sun.mail.smtp.SMTPSenderFailedException: 501

Jenkins邮件配置&#xff0c;配置完成各种信息之后&#xff0c;“通过发送测试邮件测试配置”点击Test configuration&#xff0c;报错 1、报错信息 com.sun.mail.smtp.SMTPSenderFailedException: 501 mail from address must be same as authorization userat com.sun.mail…

ARM_异常处理流程_编写软中断swi验证保存现场和恢复现场

keil .text .global _start _start:1.构建异常向量表b resetb undefb software_interruptb prefetch_abortb data_abortb .b irqb fiq reset:系统上电之后处于svc模式初始化svc模式下的栈指针ldr sp,0x400008002.从SVC模式切换到user模式 msr cpsr,#0xD0mrs r0,cpsrorr r0,r0,…

C#(五十四)之线程Mutex互斥

Mutex&#xff08;互斥体&#xff09;&#xff1a; 排他性的使用共享资源称为线程间的互斥。 使用Mutex类要比使用monitor类消耗更多的系统资源&#xff0c;但他可以跨越多个应用程序&#xff0c;在多个应用程序间同步。 构造函数 Mutex() 使用默认属性初始化 Mutex 类的新…

算法与数据结构(六)

一、图 一、临接表 表示方法如下&#xff1a; 带权值的无向图的构建&#xff1a; #define MaxInt 32767 // 极大值 #define MVNum 100 // 最大定点数 typedef int ArcType; // 边的权值类型 typedef char VerTexType; // 顶点数据类型//弧(边)的结点结构 st…

adb: failed to install .\xxxxxx.apk: Failure [INSTALL_FAILED_USER_RESTRICTED

开发者模式和USB调试均已打开&#xff0c;adb安装时报错。看了一下&#xff0c;小米手机还需要开启USB安装才行。 问题已解决