代码随想录算法训练营第31天 | 56. 合并区间、738.单调递增的数字、968.监控二叉树

一、56. 合并区间

和昨天题一样的套路,以左边界排序,比较当前区间左边界和上一区间右边界(i初始为1,区间0的边界被设为begin和end的初始值)。当有重合,更新右边界的值(max比较)。无重合则将前一个区间加入集合,更新begin和end为当前区间。

class Solution {
    public int[][] merge(int[][] intervals) {
        Arrays.sort(intervals , (a , b) -> Integer.compare(a[0],b[0]));
        List<int[]> list = new LinkedList<>();
        int begin = intervals[0][0];
        int end = intervals[0][1];
        for(int i = 1 ; i<intervals.length ; i++){
            if(intervals[i][0]<=end){
                end = Math.max(intervals[i][1],end);
            }else{
                list.add(new int[]{begin,end});
                begin = intervals[i][0];
                end = intervals[i][1];
            }
        }
        list.add(new int[]{begin,end});
        return list.toArray(new int[list.size()][]);
    }
}

二、738.单调递增的数字

一旦遇到前面的数比后面的小(非单调递增),就把前面这个数-1,而为了使结果最大,后面的数设为9,从哪个位置发生-1操作就要把后面全都复制为9,所以赋值的start等于i+1。

本题注意int、String、char[]之间的转换

class Solution {
    public int monotoneIncreasingDigits(int n) {
        String s = String.valueOf(n);
        char[] cs = s.toCharArray();
        int start = cs.length;
        for(int i = cs.length-2 ; i>=0 ; i--){
            if(cs[i]>cs[i+1]){
                cs[i]--;
                start=i+1;
            }
        }
        for(int j = start; j<cs.length ; j++){
            cs[j]='9';
        }
        return Integer.parseInt(String.valueOf(cs));
    }
}

三、968.监控二叉树

将节点分为三种类型

  1. 无摄像头覆盖记为0
  2. 有摄像头记为1
  3. 被摄像头覆盖记为2

我们需要后序遍历从下往上处理,因为叶子结点数量多,优先考虑在叶子结点节省摄像头。

递归三要素:

  1. 输入输出:输入节点,输出当前节点状态
  2. 终止条件:遇到空节点返回状态2已覆盖,这样才能使叶子结点为0,其父节点为1
  3. 单层逻辑:判断左右孩子的状态决定父节点的状态

父节点状态(单层逻辑)的依据如下:

  1. 当左右孩子都为2,即都已经被覆盖,则返回0等待自己的父节点装摄像头
  2. 当任意一个孩子为0,则需要装摄像头,返回1并count+1
  3. 当有一个孩子为1,则返回2

显然情况2应该优先于3判断,而且1和2都不满足的时候只剩下情况3,所以用else即可,所有情况都被覆盖。

根节点的特殊情况:在递归结束后,主函数中会返回根节点的状态,如果根节点为0,那自己需要装一个摄像头。

class Solution {
    int count = 0;
    public int minCameraCover(TreeNode root) {
        int a = traversal(root);
        if(a == 0) count++;
        return count;
    }

    private 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){
            count++;
            return 1;
        }
        else return 2;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值