代码随想录第三十七天——单调递增的数字,监控二叉树

leetcode 738. 单调递增的数字

题目链接:单调递增的数字
从后向前遍历,例如332的数值变化为:332 -> 329 -> 299

class Solution {
public:
    int monotoneIncreasingDigits(int N) {
        string strNum = to_string(N);
        //flag用来标记赋值9从哪里开始
        //设置为这个默认值,为了防止第二个for循环在flag没有被赋值的情况下执行
        int flag = strNum.size();
        for (int i = strNum.size() - 1; i > 0; i--)  //从后向前遍历,可以重复利用上次比较的结果
        {
            if (strNum[i - 1] > strNum[i] ) 
            {
                flag = i;
                strNum[i - 1]--;
            }
        }
        for (int i = flag; i < strNum.size(); i++) {
            strNum[i] = '9';
        }
        return stoi(strNum);
    }
};

时间复杂度:O(n),n 为数字长度
空间复杂度:O(n),需要一个字符串,转化为字符串操作更方便。

leetcode 968. 监控二叉树

题目链接:监控二叉树
局部最优:让叶子节点的父节点安摄像头,所用摄像头最少
整体最优:全部摄像头数量所用最少
本题思路:从低到上,先给叶子节点父节点放摄像头,然后隔两个节点放摄像头,直至二叉树头结点。
遍历顺序:后序遍历
用三个数字表示每个节点的状态

  • 0:该节点无覆盖
  • 1:本节点有摄像头
  • 2:本节点有覆盖

空节点的状态只能是有覆盖,方便在叶子节点的父节点放摄像头。

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) {
            res++;
            return 1;
        }

        // 情况3
        // left == 1 && right == 2 左节点有摄像头,右节点有覆盖
        // left == 2 && right == 1 左节点有覆盖,右节点有摄像头
        // left == 1 && right == 1 左右节点都有摄像头
        // 其他情况前段代码均已覆盖
        if (left == 1 || right == 1) return 2;
        return -1;
    }

public:
    int minCameraCover(TreeNode* root) {
        res = 0;
        // 情况4:递归结束了,如果头节点没有覆盖,result++
        if (traversal(root) == 0) { // root 无覆盖
            res++;
        }
        return res;
    }
};

代码简化为:

class Solution {
private:
    int res;
    int traversal(TreeNode* cur) {
        if (cur == NULL) return 2;
        int left = traversal(cur->left);    // 左
        int right = traversal(cur->right);  // 右
        if (left == 2 && right == 2) return 0;
        else if (left == 0 || right == 0) {
            res++;
            return 1;
        } else return 2;
    }
public:
    int minCameraCover(TreeNode* root) {
        res = 0;
        if (traversal(root) == 0) { // root 无覆盖
            res++;
        }
        return res;
    }
};

时间复杂度: O(n),需要遍历二叉树上的每个节点
空间复杂度: O(n)

你可能感兴趣的:(leetcode,数据结构,算法)