LeetCode738.单调递增的数字
思路:与分糖果的题目同理,因为需要与前一位数比较,并且修改这两个数,因此需要从后往前遍历,当前一位数比当前数大时,则前一个数-1,后一个数变为9。
代码细节:1、flag初始值不为0,因为当数本身就是递增序列时,不应该执行赋9操作。
2、flag=i,而不是直接赋值,因为如果当数字为1000时,并不会执行赋值操作,但是最终答案为999。
class Solution {
public:
int monotoneIncreasingDigits(int n) {
string str = to_string(n);
if(str.size()==1) return n;
int flag = str.size();
for(int i=str.size()-1;i>0;i--){
if(str[i-1]>str[i]){
str[i-1]--;
flag = i;
}
}
for(int i=flag;i<str.size();i++){
str[i] = '9';
}
int num = stoi(str);
return num;
}
};
LeetCode968.监控二叉树
贪心逻辑:如果叶子节点没有被摄像头覆盖,那么在叶子节点的父节点装摄像头。由此确定父节点的状态需要先确定其孩子的状态,因此遍历顺序为后序遍历。
为每个节点设定状态:0未被覆盖;1装摄像头;2被覆盖
当空节点时利用排除法,为了不影响其他节点的判定,只能赋值为2被覆盖状态。
代码考虑情形较多,这里贴卡哥代码如下:时间复杂度O(n),空间复杂度O(n)。
注意:中间节点的判断逻辑顺序不能发生改变,因为实际是else if 的逻辑,因为叶子节点为状态0未覆盖的判断优先级顺序高于叶子节点装摄像头的判断优先级。
class Solution {
private:
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;
}
public:
int minCameraCover(TreeNode* root) {
result = 0;
// 情况4
if (traversal(root) == 0) { // root 无覆盖
result++;
}
return result;
}
};