每日OJ题_贪心算法三⑥_力扣738. 单调递增的数字

目录

[力扣738. 单调递增的数字](#力扣738. 单调递增的数字)

解析代码


力扣738. 单调递增的数字

738. 单调递增的数字

难度 中等

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

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

示例 1:

复制代码
输入: n = 10
输出: 9

示例 2:

复制代码
输入: n = 1234
输出: 1234

示例 3:

复制代码
输入: n = 332
输出: 299

提示:

  • 0 <= n <= 10^9
cpp 复制代码
class Solution {
public:
    int monotoneIncreasingDigits(int n) {

    }
};

解析代码

下面是暴力的代码(会超时,因为找一个数的数位是logN的,总时间是O(N*logN))

cpp 复制代码
class Solution {
public:
    int monotoneIncreasingDigits(int n) {
        for(int i = n; i >= 0; --i)
        {
            string str = to_string(i);
            int j = 1, sz = str.size();
            bool flag = true;
            for(; j < sz; ++j)
            {
                if(str[j] < str[j - 1])
                {
                    flag = false;
                    break;
                }
            }
            if(flag)
                return i;
        }
        return 9;
    }
};

贪心策略: 假设有一个数 n,它有 m 位数字,每一位数字分别是 d.1, d.2 , ..., dm 。

想要修改这个数字,使得修改后的结果既小于原数字 n ,又满足单调递增和最大化。为了实现这个目标,我们需要将不满足递增的高位数字尽可能地减小。

首先需要找到一个位置 k,使得d.1 ≤ d.2 ≤ ... ≤ d.k > d.k+1 ... (例如:12335412,k=4,d.k=5)。这个位置 k 表示从高到低,第一个不满足单调递增的数字的位置。我们需要将这个数字 减1,因为这是最小的减小量。

接下来需要将低位数字都修改为9, 这样可以保证修改后的数字是最大的,并且还能保证单调递增。但是要处理找到第一个不满足单调递增的数字的位置,前面数字和此sh大小相等的情况(还是上面的k):

需要继续修改这个数字。需要找到一个位置 t ,使得d.1 ≤ d.2 ≤ ... < d.t = d.t+1 = ... = d.k。这个位置 t 表示从高到低,最后一个高位数字相等的位置。我们需要将 d.t 减 1,并将之后的所有数字都修改为9,以满足d.1 ≤ d.2 ≤ ... ≤ d.t − 1 ≤ 9 ≤ ... ≤ 9,即高位数字的单调递增和低位数字的最大化。例如:1224444361,成功修改后的最大值为1223999999。

通过这种修改方式,可以得到一个新的数字,它既小于原数字 n,又满足单调递增和最大化。

cpp 复制代码
class Solution {
public:
    int monotoneIncreasingDigits(int n) {
        string s = to_string(n);
        int i = 0, m = s.size();
        while(i + 1 < m && s[i] <= s[i + 1])
            i++; // 找第⼀个递减的位置

        if(i == m - 1) // 如果没有递减的
            return n; 

        while(i - 1 >= 0 && s[i] == s[i - 1])
            --i; // 回推

        --s[i]; // 开始修改
        for(int j = i + 1; j < m; ++j)
            s[j] = '9';
        return stoi(s);
    }
};
相关推荐
cherub.2 分钟前
深入解析信号量:定义与环形队列生产消费模型剖析
linux·c++
机器学习之心4 分钟前
一区北方苍鹰算法优化+创新改进Transformer!NGO-Transformer-LSTM多变量回归预测
算法·lstm·transformer·北方苍鹰算法优化·多变量回归预测·ngo-transformer
yyt_cdeyyds15 分钟前
FIFO和LRU算法实现操作系统中主存管理
算法
暮色_年华16 分钟前
Modern Effective C++item 9:优先考虑别名声明而非typedef
c++
重生之我是数学王子25 分钟前
QT基础 编码问题 定时器 事件 绘图事件 keyPressEvent QT5.12.3环境 C++实现
开发语言·c++·qt
alphaTao42 分钟前
LeetCode 每日一题 2024/11/18-2024/11/24
算法·leetcode
我们的五年1 小时前
【Linux课程学习】:进程程序替换,execl,execv,execlp,execvp,execve,execle,execvpe函数
linux·c++·学习
kitesxian1 小时前
Leetcode448. 找到所有数组中消失的数字(HOT100)+Leetcode139. 单词拆分(HOT100)
数据结构·算法·leetcode
做人不要太理性1 小时前
【C++】深入哈希表核心:从改造到封装,解锁 unordered_set 与 unordered_map 的终极奥义!
c++·哈希算法·散列表·unordered_map·unordered_set
程序员-King.1 小时前
2、桥接模式
c++·桥接模式