今天是贪心算法的终点,难度也是直线上升。
第一题:
简介:
本题刚开始思考时跟着思路写出了暴力算法,但是超时了。然后,看到了本题的贪心思想
例如98,一旦出现strNum()[i - 1] > strNum[i]的情况(非单调递增),首先想让strNum[i - 1]减一,strNum[i]赋值9,这样这个整数就是89。就可以很自然想到对应的贪心解法了。
想到了贪心,还要考虑遍历顺序,只有从后向前遍历才能重复利用上次比较的结果。
最后代码实现的时候,也需要一些技巧,例如用一个flag来标记从哪里开始赋值9。
代码实现:
暴力方法:
class Solution {
public:
int monotoneIncreasingDigits(int n) {
if(n == 10)return 9;
if(n < 10) return n;
bool handle =true;
int pre= INT_MIN;
int cur=0;
int num =n;
int result;
while(num != 0){
if(pre == INT_MIN){
pre = num%10;
num = num/10;
continue;
}
cur = num%10;
if(cur<=pre){
pre = cur;
num = num/10;
continue;
}else{
handle =false;
break;
}
}
if(handle == true)return n;
else{
for(int i = n;i>0;i--){
handle = true;
num =i;
pre= INT_MIN;
while(num != 0){
if(pre == INT_MIN){
pre = num%10;
num = num/10;
continue;
}
cur = num%10;
if(cur <= pre){
pre = cur;
num = num/10;
continue;
}else{
handle =false;
break;
}
}
if(handle == true){
return i;
}
}
}
return 0;
}
};
贪心思想:
第二题:

简介:
本题可以说是二叉树与贪心思想的结合。建议去看代码随想录卡哥的教程,讲得很清晰。代码随想录:监控二叉树
代码实现:
class Solution {
public:
int result;
int traversal(TreeNode* cur) {
// 空节点,该节点有覆盖
if (cur == NULL) return 2;
int left = traversal(cur->left); // 左
int right = traversal(cur->right); // 右
// 情况1
// 左右节点都有覆盖
if (left == 2 && right == 2) return 0;
// 情况2
// left == 0 && right == 0 左右节点无覆盖
// left == 1 && right == 0 左节点有摄像头,右节点无覆盖
// left == 0 && right == 1 左节点有无覆盖,右节点摄像头
// left == 0 && right == 2 左节点无覆盖,右节点覆盖
// left == 2 && right == 0 左节点覆盖,右节点无覆盖
if (left == 0 || right == 0) {
result++;
return 1;
}
// 情况3
// left == 1 && right == 2 左节点有摄像头,右节点有覆盖
// left == 2 && right == 1 左节点有覆盖,右节点有摄像头
// left == 1 && right == 1 左右节点都有摄像头
// 其他情况前段代码均已覆盖
if (left == 1 || right == 1) return 2;
// 以上代码我没有使用else,主要是为了把各个分支条件展现出来,这样代码有助于读者理解
// 这个 return -1 逻辑不会走到这里。
return -1;
}
int minCameraCover(TreeNode* root) {
result = 0;
// 根节点没有摄像头覆盖
if (traversal(root) == 0) { // root 无覆盖
result++;
}
return result;
}
};
总结:
今天是贪心算法的最后一节,贪心思想总体写下来,也是愈来愈难,总体来说,贪心思想的题没有固定的套路和模板,这就需要多听,多看,多练,来提高自己的敏感度。继续加油!