代码随想录算法训练营第三七天 | 单调递增的数字、监控二叉树

目录

  • 单调递增的数字
  • 监控二叉树

LeetCode 738.单调递增的数字
LeetCode 968.监控二叉树

单调递增的数字

当且仅当每个相邻位数上的数字 x 和 y 满足 x <= y 时,我们称这个整数是单调递增的。

给定一个整数 n ,返回 小于或等于 n 的最大数字,且数字呈 单调递增 。

思路:

  • 转成 str 字符串、再转成 char[] 数组,从后向前遍历,遇到 chars[i - 1] > chars[i] 的情况,chars[i - 1]–;
  • 同时设置一个变量记录从第几位开始后面都是9, 再写一个 for 循环遍历设置为9.
  • 最后 Integer.parseInt(String.valueOf(chars))
class Solution {
    public int monotoneIncreasingDigits(int n) {
        String str = String.valueOf(n);
        char[] chars = str.toCharArray();
        int start = chars.length; // 记录从第几位开始后面都是9  eg:100
        for (int i = chars.length - 1; i > 0; i--) {
            if (chars[i - 1] > chars[i]) {
                chars[i - 1]--;
                start = i;
            }
        }
        for (int i = start; i < chars.length; i++) {
            chars[i] = '9';
        }

        return Integer.parseInt(String.valueOf(chars));
    }
}

监控二叉树

给定一个二叉树,我们在树的节点上安装摄像头。

节点上的每个摄影头都可以监视其父对象、自身及其直接子对象。

计算监控树的所有节点所需的最小摄像头数量。

思路: 题目示例中的摄像头都没有放在叶子节点上!

  • 要从下往上看,局部最优:让叶子节点的父节点安摄像头,所用摄像头最少,整体最优:全部摄像头数量所用最少!
  • 从低到上,先给叶子节点父节点放个摄像头,然后隔两个节点放一个摄像头,直至到二叉树头结点。
  • 遍历顺序:后序遍历 左右中,在回溯的过程中从下到上进行推导。
  • 隔两个节点放一个摄像头:每个节点可能有几种状态:
    • 0:该节点无覆盖
    • 1:本节点有摄像头
    • 2:本节点有覆盖
  • 空节点的状态只能是有覆盖,这样就可以在叶子节点的父节点放摄像头了

情况1:左右节点都有覆盖
左孩子有覆盖,右孩子有覆盖,那么此时中间节点应该就是无覆盖的状态了。
if (left == 2 && right == 2) return 0;

代码随想录算法训练营第三七天 | 单调递增的数字、监控二叉树_第1张图片

情况2:左右节点至少有一个无覆盖的情况
如果是以下情况,则中间节点(父节点)应该放摄像头:
left == 0 && right == 0 左右节点无覆盖
left == 1 && right == 0 左节点有摄像头,右节点无覆盖
left == 0 && right == 1 左节点有无覆盖,右节点摄像头
left == 0 && right == 2 左节点无覆盖,右节点覆盖
left == 2 && right == 0 左节点覆盖,右节点无覆盖
此时摄像头的数量要加一,并且return 1,代表中间节点放摄像头。
if (left == 0 || right == 0) {
result++;
return 1;
}

情况3:左右节点至少有一个有摄像头
如果是以下情况,其实就是 左右孩子节点有一个有摄像头了,那么其父节点就应该是2(覆盖的状态)
left == 1 && right == 2 左节点有摄像头,右节点有覆盖
left == 2 && right == 1 左节点有覆盖,右节点有摄像头
left == 1 && right == 1 左右节点都有摄像头
if (left == 1 || right == 1) return 2;

情况4:头结点没有覆盖
以上都处理完了,递归结束之后,可能头结点 还有一个无覆盖的情况。
所以递归结束之后,还要判断根节点,如果没有覆盖,result++。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    int res = 0;
    public int minCameraCover(TreeNode root) {
        // 对根节点的状态做检验,防止根节点是无覆盖状态 .
        if (minCame(root) == 0) res++;
        return res;
    }
    
    private int minCame(TreeNode root) {
        if (root == null) {
            return 2; // 空节点默认为 有覆盖状态,避免在叶子节点上放摄像头
        }
        int left = minCame(root.left);
        int right = minCame(root.right);

        // 如果左右节点都覆盖了的话, 那么本节点的状态就应该是无覆盖,没有摄像头
        if (left == 2 && right == 2) {
            return 0;
        }
        else if (left == 0 || right == 0) {
            // 左右节点都是无覆盖状态,那 根节点此时应该放一个摄像头
            // (0,0) (0,1) (0,2) (1,0) (2,0)
            // 状态值为 1 摄像头数 ++;
            res++;
            return 1;
        }
        else {
            // 左右节点的 状态为 (1,1) (1,2) (2,1) 也就是左右节点至少存在 1个摄像头,
            // 那么本节点就是处于被覆盖状态
            return 2;
        }
    }
}

你可能感兴趣的:(算法)