一、LeetCode 738.单调递增的数字
题目链接/文章讲解/视频讲解:https://programmercarl.com/0738.%E5%8D%95%E8%B0%83%E9%80%92%E5%A2%9E%E7%9A%84%E6%95%B0%E5%AD%97.html
状态:已解决
1.思路
如何求得小于等于N的最大单调递增的整数?98,一旦出现strNum[i - 1] > strNum[i]的情况(非单调递增),首先想让strNum[i - 1]--,然后strNum[i]给为9,这样这个整数就是89,即小于98的最大的单调递增整数。也就是说,我们只需要找到最先不满足单增性质的位置,然后将前一个元素-1,后面的所有元素变为9即可。因此,代码分两步:
(1)找到整数中最先不满足单增性质的前后元素:
遍历数组,比较前后两个元素的大小,然后不断维护前者大于后者的最新下标。此时是从前向后遍历还是从后向前遍历呢?从前向后遍历的话,遇到strNum[i - 1] > strNum[i]的情况,让strNum[i - 1]减一,但此时如果strNum[i - 1]减一了,可能又小于strNum[i - 2]。这么说有点抽象,举个例子,数字:332,从前向后遍历的话,那么就把变成了329,此时2又小于了第一位的3了,真正的结果应该是299。那么从后向前遍历,就可以重复利用上次比较得出的结果了,从后向前遍历332的数值变化为:332 -> 329 -> 299。
(2)后面所有元素变为9
从维护的位置开始,到整数末,每个数都变为9。
2.代码实现
class Solution {
public:
int monotoneIncreasingDigits(int n) {
string s = to_string(n);
int pos = s.size();//注意初值值设为数组末,以便找不到不符合单增性质的位置时,
//让第二个循环不做
for(int i=s.size()-1;i>0;i--){
if(s[i-1] > s[i]){
s[i-1]--;
pos = i;
}
}
for(int i=pos;i<s.size();i++){
s[i] = '9';
}
return stoi(s);
}
};
二、总结
1.贪心简单题
以下三道题目就是简单题,可以初步理解贪心的概念。
- 贪心算法:分发饼干(opens new window)
- 贪心算法:K次取反后最大化的数组和(opens new window)
- 贪心算法:柠檬水找零
2.贪心中等题
(1)这两类属于第一次接触较为难想的题,偏数学。
- 贪心算法:摆动序列(opens new window)
- 贪心算法:单调递增的数字
(2)贪心解决股票问题
一般的股票问题是动规的领域,但部分用贪心也可以解决,以下是比较经典的两道可以贪心完成的股票问题。
- 贪心算法:买卖股票的最佳时机II(opens new window)
- 贪心算法:买卖股票的最佳时机含手续费 (opens new window)本题使用贪心算法比较绕,建议后面学习动态规划章节的时候,理解动规就好
(3)两个维度的题
在出现两个维度相互影响的情况时,两边一起考虑一定会顾此失彼,要先确定一个维度,再确定另一个一个维度。
- 贪心算法:分发糖果(opens new window)
- 贪心算法:根据身高重建队列
3.贪心难题
(1)贪心解决区间问题
主要是一些区间覆盖问题,如何统计如何去除。
- 贪心算法:跳跃游戏(opens new window)
- 贪心算法:跳跃游戏II(opens new window)
- 贪心算法:用最少数量的箭引爆气球(opens new window)
- 贪心算法:无重叠区间(opens new window)
- 贪心算法:划分字母区间(opens new window)
- 贪心算法:合并区间
(2)无规律的题
贪心算法:最大子序和 (opens new window)
贪心算法:加油站 (opens new window)