代码随想录算法训练营-Day31

题目

56. 合并区间

题解:

class Solution {
    public int[][] merge(int[][] intervals) {
        if (intervals.length == 0) return new int[0][0]; // 特殊情况处理

        List<int[]> ansList = new ArrayList<>();
        
        // 1. 排序
        Arrays.sort(intervals, (a,b) -> Integer.compare(a[0], b[0]));

        for(int i = 1; i < intervals.length; i++) {
            // 2. 判断重叠
            if(intervals[i][0] <= intervals[i-1][1]) {
                // 有重叠:合并
                // 把前一个的 start 传给当前 (保持最小 start)
                intervals[i][0] = intervals[i-1][0]; 
                // 更新当前的 end 为两者最大 end
                intervals[i][1] = Math.max(intervals[i][1], intervals[i-1][1]);
                // 注意:这里不添加进 list,因为这个合并后的新区间可能还会和后面重叠
            } else {
                // 无重叠:说明 i-1 已经处理完毕,可以安全加入结果集
                ansList.add(intervals[i-1]);
            }
        }

        // 3. 循环结束后,必须把最后一个区间加入
        // 无论它是被合并过的,还是独立的,它都还留在 intervals 数组的最后一位
        ansList.add(intervals[intervals.length - 1]);

        // 4. 转为二维数组
        return ansList.toArray(new int[ansList.size()][]);
    }
}
738. 单调递增的数字

题解:

class Solution {
    public int monotoneIncreasingDigits(int n) {
        String s = String.valueOf(n);
        char[] chars = s.toCharArray();
        
        // start 用来记录从哪里开始把后面全变成 9
        // 初始化为 length,防止不需要变的情况(如 1234)
        int start = chars.length; 

        // 1. 从后向前遍历
        for (int i = chars.length - 1; i > 0; i--) {
            // 如果前一位 > 后一位(出现逆序)
            if (chars[i - 1] > chars[i]) {
                // 前一位减 1
                chars[i - 1]--;
                // 记录当前位置 i 为“变成9的起始点”
                start = i;
            }
        }

        // 2. 统一将标记点之后的所有位变成 9
        // 这一步必须放在循环外面做,因为 start 可能会不断向前更新
        // 比如 100 -> 099,如果不更新 start,可能中间会有没变成 9 的
        for (int i = start; i < chars.length; i++) {
            chars[i] = '9';
        }

        return Integer.parseInt(new String(chars));
    }
}
968. 监控二叉树

题解:

class Solution {
    int res = 0; // 记录摄像头数量

    public int minCameraCover(TreeNode root) {
        // 后序遍历(从下往上)
        // 如果最后根节点返回 0 (无覆盖),说明根节点需要一个摄像头
        if (minCameraCoverDfs(root) == 0) {
            res++;
        }
        return res;
    }

    /**
     * @return 
     * 0: 无覆盖 (Not Covered)
     * 1: 有摄像头 (Has Camera)
     * 2: 已覆盖 (Covered)
     */
    private int minCameraCoverDfs(TreeNode node) {
        // Base Case: 空节点视为“已覆盖”,这样叶子节点就会被判断为“无覆盖”
        if (node == null) return 2;

        int left = minCameraCoverDfs(node.left);
        int right = minCameraCoverDfs(node.right);

        // 逻辑顺序很重要,必须先判断是否需要装摄像头

        // Case 1: 左右孩子只要有一个没被覆盖,我就必须装摄像头
        if (left == 0 || right == 0) {
            res++;
            return 1; // 我装了摄像头
        }

        // Case 2: 左右孩子只要有一个有摄像头,我就被覆盖了
        // (前提是 Case 1 不满足,说明没有孩子是 0)
        if (left == 1 || right == 1) {
            return 2; // 我被覆盖了
        }

        // Case 3: 左右孩子都是已覆盖 (2),那我就没人管了
        // 我变成了无覆盖,等待父节点处理
        return 0;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值