当前位置: 首页 > 科技观察

数据结构与算法:数字单调递增

时间:2023-03-23 10:16:51 科技观察

数字单调递增链接:https://leetcode-cn.com/problems/monotone-increasing-digits给定一个非负整数N,判断它是否小于或等于等于N的最大整数,这个整数需要满足其位数单调递增的要求。(我们说一个整数单调递增当且仅当每个相邻数字中的数字x和y满足x<=y。)示例1:输入:N=10输出:9示例2:输入:N=1234输出:1234示例3:输入:N=332输出:299解释:N是[0,10^9]范围内的整数。暴力破解的意思很简单,所以我首先想到的就是暴力破解。我给大家暴力一波,结果超时!代码如下:classSolution{private:boolcheckNum(intnum){intmax=10;while(num){intt=num%10;if(max>=t)max=t;elsereturnfalse;num=num/10;}returntrue;}public:intmonotoneIncreasingDigits(intN){for(inti=N;i>0;i--){if(checkNum(i))returni;}return0;}};时间复杂度:O(n*m)m为n的数长度空间复杂度:O(1)贪心算法题目要求最大单调小于等于N的自增整数,则以一个两位数为例.例如:98,一旦出现strNum[i-1]>strNum[i](非单调递增),先令strNum[i-1]--,则strNum[i]为9,所以这个整数为89,小于98的最大单调递增整数。如果把这一点想清楚了,这道题就好办了。LocalOptimum:在strNum[i-1]>strNum[i]的情况下,令strNum[i-1]--,则strNum[i]为9,可以保证这两位成为最大的单调递增整数。全局最优:得到小于等于N的最大单调递增整数。但是这里局部最优导致全局最优,还需要其他条件,就是遍历的顺序,标记的哪一位开始统一变为9。这时候是不是从前面遍历到向后还是从后向前?如果是从前向后遍历,如果遇到strNum[i-1]>strNum[i],让strNum[i-1]减一,但此时如果strNum[i-1]减一一,它可能小于strNum[i-2]。这个有点抽象。比如数字:332,如果从前向后遍历,那么就变成了329,此时2比前3小了,真正的结果应该是299。所以从前向后遍历会改变已经遍历的结果!那么从后往前遍历就可以复用上次比较的结果。从后向前遍历332的值变为:332->329->299遍历顺序确定后,那么此时就可以在全局情况下引入局部最优。如果找不到反例,请尝试贪婪。C++代码如下:classSolution{public:intmonotoneIncreasingDigits(intN){stringstrNum=to_string(N);//flag用来标记赋值9从哪里开始//设置为这个默认值,是为了防止第二次forloopwhenflagisnotset赋值的情况下,执行intflag=strNum.size();for(inti=strNum.size()-1;i>0;i--){if(strNum[i-1]>strNum[i]){flag=i;strNum[i-1]--;}}for(inti=flag;i在strNum[i](非单调递增)的情况下,我们首先要将strNum[i-1]减一,给strNum[i]赋值9,使得整数为89。很自然地想到对应的贪心解法。想到贪心,还要考虑遍历顺序。只有从后往前遍历,才能复用上次比较的结果。最终代码实现的时候,还需要一些tricks,比如用一个flag来标记从哪里开始赋值9。其他语言版本Java:Version1classSolution{publicintmonotoneIncreasingDigits(intN){String[]strings=(N+"").split("");intstart=strings.length;for(inti=strings.length-1;i>0;i--){if(Integer.parseInt(strings[i])0;i--){if(chars[i]=st艺术){res.append('9');}elseres.append(chars[i]);}returnInteger.parseInt(res.toString());}}Python:classSolution:defmonotoneIncreasingDigits(self,n:int)->int:a=list(str(n))foriinrange(len(a)-1,0,-1):ifint(a[i])0;i--{ifss[i-1]>ss[i]{//前一位大于后一位,前一位负1,后面的全部设为9ss[i-1]-=1forj:=i;j{return+item})letflag=Infinityfor(leti=n.length-1;i>0;i--){if(n[i-1]>n[i]){flag=in[i-1]=n[i-1]-1n[i]=9}}for(leti=flag;i

最新推荐
猜你喜欢