文章目录
day31 贪心算法(05)
以数组 <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()][]);
}
}
- 排序:
- 按区间的起始位置进行排序。如果起始位置相同,则按结束位置进行排序。
- 合并区间:
- 初始化一个结果列表
<font style="color:rgb(44, 44, 54);">merged</font>
。 - 遍历排序后的区间:
- 如果当前区间的起始位置大于结果列表中最后一个区间的结束位置,则将当前区间直接加入结果列表。
- 否则,合并当前区间和结果列表中最后一个区间,更新结果列表中最后一个区间的结束位置为两者结束位置的最大值。
- 初始化一个结果列表
- 返回结果:
- 返回结果列表
<font style="color:rgb(44, 44, 54);">merged</font>
。
- 返回结果列表
当且仅当每个相邻位数上的数字 <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));
}
}
- 将数字转换为字符数组:
- 将输入的整数
<font style="color:rgb(44, 44, 54);">N</font>
转换为字符数组,方便逐位处理。
- 将输入的整数
- 从高位到低位检查:
- 从高位到低位遍历字符数组,检查每一位数字是否满足单调递增的条件。
- 如果发现某一位数字不满足条件,将该位数字减 1,并将其后面的所有位数字变为 9。
- 将字符数组转换回整数:
- 将处理后的字符数组转换回整数并返回。
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};
}
}
- 状态定义:
○ 状态 0:当前节点未被监控。
○ 状态 1:当前节点被监控,但没有摄像头。
○ 状态 2:当前节点有摄像头。 - 递归函数 dfs:
○ 如果当前节点为空,返回 [0, 0, Integer.MAX_VALUE / 2],表示空节点不需要监控。
○ 递归计算左子树和右子树的状态。
○ 计算当前节点处于状态 0、1、2 时所需的最小摄像头数量:
■ 状态 0:当前节点未被监控,左右子树必须都被监控,但没有摄像头。
■ 状态 1:当前节点被监控,但没有摄像头。可以通过左子树或右子树有摄像头来实现。
■ 状态 2:当前节点有摄像头,左右子树可以处于任何状态。 - 主函数 minCameraCover:
○ 调用 dfs 函数计算根节点的状态。
○ 返回根节点处于状态 1 或 2 时的最小摄像头数量。小摄像头数量。