代码随想录day31 贪心算法05

day31 贪心算法(05)

56. 合并区间

以数组 <font style="color:rgba(38, 38, 38, 0.75);background-color:#FFFFFF;">intervals</font> 表示若干个区间的集合,其中单个区间为 <font style="color:rgba(38, 38, 38, 0.75);background-color:#FFFFFF;">intervals[i] = [start</font><sub><font style="color:rgba(38, 38, 38, 0.75);background-color:#FFFFFF;">i</font></sub><font style="color:rgba(38, 38, 38, 0.75);background-color:#FFFFFF;">, end</font><sub><font style="color:rgba(38, 38, 38, 0.75);background-color:#FFFFFF;">i</font></sub><font style="color:rgba(38, 38, 38, 0.75);background-color:#FFFFFF;">]</font> 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间

示例 1:

输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].

示例 2:

输入:intervals = [[1,4],[4,5]]
输出:[[1,5]]
解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。
import java.util.Arrays;
import java.util.ArrayList;

class Solution {
    public int[][] merge(int[][] intervals) {
        if (intervals.length == 0) {
            return new int[0][2];
        }

        // 按区间的起始位置进行排序
        Arrays.sort(intervals, (a, b) -> a[0] - b[0]);

        // 初始化结果列表
        ArrayList<int[]> merged = new ArrayList<>();
        merged.add(intervals[0]);

        // 遍历排序后的区间
        for (int i = 1; i < intervals.length; i++) {
            int[] current = intervals[i];
            int[] lastMerged = merged.get(merged.size() - 1);

            if (current[0] > lastMerged[1]) {
                // 当前区间的起始位置大于结果列表中最后一个区间的结束位置
                merged.add(current);
            } else {
                // 合并当前区间和结果列表中最后一个区间
                lastMerged[1] = Math.max(lastMerged[1], current[1]);
            }
        }

        // 将结果列表转换为数组
        return merged.toArray(new int[merged.size()][]);
    }
}
  1. 排序
    • 按区间的起始位置进行排序。如果起始位置相同,则按结束位置进行排序。
  2. 合并区间
    • 初始化一个结果列表 <font style="color:rgb(44, 44, 54);">merged</font>
    • 遍历排序后的区间:
      • 如果当前区间的起始位置大于结果列表中最后一个区间的结束位置,则将当前区间直接加入结果列表。
      • 否则,合并当前区间和结果列表中最后一个区间,更新结果列表中最后一个区间的结束位置为两者结束位置的最大值。
  3. 返回结果
    • 返回结果列表 <font style="color:rgb(44, 44, 54);">merged</font>

738. 单调递增的数字

当且仅当每个相邻位数上的数字 <font style="color:rgba(38, 38, 38, 0.75);background-color:#FFFFFF;">x</font><font style="color:rgba(38, 38, 38, 0.75);background-color:#FFFFFF;">y</font> 满足 <font style="color:rgba(38, 38, 38, 0.75);background-color:#FFFFFF;">x <= y</font> 时,我们称这个整数是单调递增的。

给定一个整数 <font style="color:rgba(38, 38, 38, 0.75);background-color:#FFFFFF;">n</font> ,返回 小于或等于__ _<font style="color:rgba(38, 38, 38, 0.75);background-color:#FFFFFF;">n</font>_ 的最大数字,且数字呈 __单调递增

示例 1:

输入: n = 10
输出: 9

示例 2:

输入: n = 1234
输出: 1234

示例 3:

输入: n = 332
输出: 299
class Solution {
    public int monotoneIncreasingDigits(int N) {
        char[] digits = Integer.toString(N).toCharArray();
        int n = digits.length;

        // 标记第一个需要减 1 的位置
        int flag = n;

        for (int i = n - 1; i > 0; i--) {
            if (digits[i] < digits[i - 1]) {
                flag = i;
                digits[i - 1]--;
            }
        }

        // 将标记位置及其后面的数字变为 9
        for (int i = flag; i < n; i++) {
            digits[i] = '9';
        }

        // 将字符数组转换回整数
        return Integer.parseInt(new String(digits));
    }
}
  1. 将数字转换为字符数组
    • 将输入的整数 <font style="color:rgb(44, 44, 54);">N</font> 转换为字符数组,方便逐位处理。
  2. 从高位到低位检查
    • 从高位到低位遍历字符数组,检查每一位数字是否满足单调递增的条件。
    • 如果发现某一位数字不满足条件,将该位数字减 1,并将其后面的所有位数字变为 9。
  3. 将字符数组转换回整数
    • 将处理后的字符数组转换回整数并返回。

968. 监控二叉树
这个是难题,跳过

/**
 * 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 {
    public int minCameraCover(TreeNode root) {
        int[] res = dfs(root);
        // 返回根节点处于状态 1 或 2 时的最小摄像头数量
        return Math.min(res[1], res[2]);
    }

    private int[] dfs(TreeNode node) {
        if (node == null) {
            // 空节点不需要监控
            return new int[]{0, 0, Integer.MAX_VALUE / 2};
        }

        int[] left = dfs(node.left);
        int[] right = dfs(node.right);

        // 状态 0:当前节点未被监控
        int state0 = left[1] + right[1];

        // 状态 1:当前节点被监控,但没有摄像头
        int state1 = Math.min(left[2] + Math.min(right[1], right[2]), right[2] + Math.min(left[1], left[2]));

        // 状态 2:当前节点有摄像头
        int state2 = Math.min(Math.min(left[0], left[1]), left[2]) + Math.min(Math.min(right[0], right[1]), right[2]) + 1;

        return new int[]{state0, state1, state2};
    }
}
  1. 状态定义:
    ○ 状态 0:当前节点未被监控。
    ○ 状态 1:当前节点被监控,但没有摄像头。
    ○ 状态 2:当前节点有摄像头。
  2. 递归函数 dfs:
    ○ 如果当前节点为空,返回 [0, 0, Integer.MAX_VALUE / 2],表示空节点不需要监控。
    ○ 递归计算左子树和右子树的状态。
    ○ 计算当前节点处于状态 0、1、2 时所需的最小摄像头数量:
    ■ 状态 0:当前节点未被监控,左右子树必须都被监控,但没有摄像头。
    ■ 状态 1:当前节点被监控,但没有摄像头。可以通过左子树或右子树有摄像头来实现。
    ■ 状态 2:当前节点有摄像头,左右子树可以处于任何状态。
  3. 主函数 minCameraCover:
    ○ 调用 dfs 函数计算根节点的状态。
    ○ 返回根节点处于状态 1 或 2 时的最小摄像头数量。小摄像头数量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值