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;// 情况4if (traversal(root) == 0) { // root 无覆盖result++;}return result;}
};