738.单调递增的数字

  • 738.单调递增的数字

  • 题目:
    给一个非负整数N,返回一个<=N的最大整数,其从高到低的每位数递增;

  • 思路:
    1.贪心 O(n):n为数字长度 ,O(n) :需要一个数字长度大小的字符串,便于操作
    若使用暴力解法,判断N不行就判断N-1,会超时,因此需设法少判断一些数字;
    整数N转换为字符串便于操作;
    nums[ i ] > num[ i - 1 ],则num[ i - 1 ] --,num[ i ] = ‘9’,例如N=85应返回79;
    只能从后往前遍历:①对N的减小最弱,才能找到满足递增的最大整数 ②在遍历过程中可以利用前面修改的结果,而不会破坏前面的工作 ,例如N=220,从前往后边里会返回219,从后往前会返回199;
    从后往前遍历过程中,不能直接num[ i ] = ‘9’,而只能flag = i记录下来需要变为9的位置,直到遍历结束,从最靠左的flag开始全置为9(因为一旦一个位置置为‘9’,要想满足递增,后面只能为‘9’)。若直接原地需改,例如 100会被改为90,而不是正确值99

class Solution {
private:
public:
    int monotoneIncreasingDigits(int N) {      
        if (N < 10) return N;
        
        string num = to_string(N);//把整数N转换为字符串。比挨着遍历并用一个vector存好多了
        //flag表示最前面需要变为9的位置
        //初始值置为这个,表示N直接就是递增的数字
        int flag = num.size();
        for (int i = num.size() - 1; i > 0; --i) {
            if (num[i - 1] > num[i]) {
                flag = i; 
                --num[i - 1];
            }
        }
        for (int i = flag; i < num.size(); ++i) {
            num[i] = '9';
        }
        
        return stoi(num);//把字符串转换为整数
    }
};

2.无敌大佬解法:最多循环9次,我直接原地膜拜
由于结果要求各位数字单调递增,那么这些数字必然形如 a0a1a2……an (1 <= a0 <= a1 <= a2 <= …… <= an <= 9);
由于题目N = [ 0, 10 ^ 9 ],因此不超过N的最大整数最多为9位数;
结果一定是由长度不同的形如111111111的数的和组成;

class Solution {
private:
public:
    int monotoneIncreasingDigits(int N) {      
        int t = 111111111;
        int res = 0;
        for (int i = 0; i < 9 && t;++i) { 
            while (res + t > N) t /= 10;
            res += t;
        }
        return res;
    }
};
  • 总结:
    转换为string:to_string;
    整数N转换为字符串便于操作;
    string[ i ] = ‘9’ 而不是 string[ i ] = 9;
    从后往前遍历而不能从前往后:只有从后往前才能重复利用上次比较的结果,且不会破坏之前做的工作;
    从后往前遍历过程中,不能直接num[ i ] = ‘9’:只能先 flag = i 记录下来需要变为9的位置,直到遍历结束,从最靠左的flag开始全置为9(因为一旦一个位置置为‘9’,要想满足递增,后面只能为‘9’)。若直接原地需改,例如 N=100,应返回99,而不是90;
    string转换为int:int stoi ( const string& ); int atoi (const char* );
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值