LeetCode—738. Monotone Increasing Digits

LeetCode题目描述

Given a non-negative integer N, find the largest number that is less than or equal to N with monotone increasing digits.
(Recall that an integer has monotone increasing digits if and only if each pair of adjacent digits x and y satisfy x <= y.)
Note: N is an integer in the range [0, 10^9].

给一个非负整数N,找出最大的、不大于N的monotone increasing digits X。所谓monotone increasing digits 指的是从左往右看,每位数字都是单调非减,如12345, 12233。
X要满足两个条件,①X<=N且X要尽可能大 ②X的各位数字dandianfeijian。该怎么找这样的数字呢?从哲学的角度想,解铃还须系铃人,肯定要从N入手。
首先如果N本身就是monotone increasing digits ,那么X=N;如果N不是,那么就需要依据N构造出X。要满足条件①,从高位开始X的数字要和N的数字尽可能相等;当不能相等时(假设是第i位),也就是为了满足条件②,我们只能第i-1位数字减小,i-1后的数字变为9。
以N=1234532为例:
N = 1 2 3 4 5 3 2
X = 1 2 3 4 5 _ _
第i=6位时,X的第6位如果取3则不满足条件②,又不能取一个更大的数字,这样会违反条件①,这种情况下只能让第i-1=5位数字减一:
N = 1 2 3 4 5 3 2
X = 1 2 3 4 4 _ _
此时X已经小于N,故后面的数字全取9也不会大于N,同时也满足条件②。
看起来这样已经解决这个问题了,其实我们忽略了一个地方,那就是第i-1位减一后,可能会出现 Xi2>Xi1 的情况,这样就违反了条件②。如:33321
N = 3 3 3 2 1
X = 3 3 2 9 9(之前做法得到的结果)
所以我们还需要向前检查,当发生 Xi1>Xi 的情况时, Xi1 -= 1, 继续向前检查,直到满足 Xi1Xi , 然后从i开始所有的数字取9。
N = 3 3 3 2 1
X = 2 9 9 9 9

class Solution {
public:
    int monotoneIncreasingDigits(int N) {
        string str = to_string(N);
        int len = str.size();
        if (len == 1) return N;
        for (int i = 1;i < len;++i){
            if (str[i] < str[i-1]){//找到违反单调不减的下标
                int t = i;
                while (t>=1 && str[t-1]>str[t]){//向前检查
                    --str[t-1];
                    --t;
                }
                for (int k =t+1;k < len;++k)//t之后的数字取9
                    str[k] = '9';
                break;
            }
        }
        cout << str << endl;
        return atoi(str.c_str());
    }
};

看到还有人的做法如下:

解题思路:
从高位向低位遍历整数N的各位数,找到第一个违反单调不减的数的下标x
将x及x后的所有数替换为0,记得到的新数为M,则M - 1即为答案

class Solution(object):
def monotoneIncreasingDigits(self, N):
"""
:type N: int
:rtype: int
"""
sn = str(N)
size = len(sn)
flag = False
for x in range(size - 1):
if sn[x] > sn[x + 1]:
flag = True
break
if not flag: return N
while x > 0 and sn[x - 1] == sn[x]: x -= 1
y = len(sn) - x - 1
return (N / (10 ** y)) * (10 ** y) - 1

博客链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值