56. 合并区间
妙:
更新右边界时,不用 i - 1,而是用 result 数组的最后一个元素的右边界。这样直接就更新了,不用删除再插入。
class Solution {
public int[][] merge(int[][] intervals) {
int n = intervals.length;
Arrays.sort(intervals, Comparator.comparingInt(a -> a[0]));
List<int[]> result = new ArrayList<>();
result.add(intervals[0]);
for (int i = 1; i < n; i++) {
if (intervals[i][0] <= result.getLast()[1]) {
// 更新右边界,不用更新左边界(左边界仍为上一个的左边界,因为已按左边界排序)
result.getLast()[1] = Math.max(result.getLast()[1], intervals[i][1]);
} else {
result.add(intervals[i]);
}
}
return result.toArray(new int[0][]);
}
}
738. 单调递增的数字
思路:
从后向前遍历,遇到前一位大于后一位,前一位减 1,后一位及之后全部赋成 9.
设置一个 flag,表示从这一位开始后面的元素全部赋成 9(防止 1000 -> 0900 的情况,应该是 1000 -> 999)
class Solution {
public int monotoneIncreasingDigits(int n) {
String str = String.valueOf(n);
char[] arr = str.toCharArray();
int len = str.length();
int flag = len; // flag 初值赋为 len,以应对给的数本来就是单调递增的情况
for (int i = len - 1; i > 0; i--) {
if (arr[i - 1] > arr[i]) {
arr[i - 1] -= 1;
flag = i;
}
}
for (int i = flag; i < len; i++) {
arr[i] = '9';
}
return Integer.parseInt(String.valueOf(arr));
}
}
968. 监控二叉树
后序(左右中)
每个节点,只有 3 种状态:
0 -> 无覆盖(未被摄像头覆盖)
1 -> 有摄像头
2 -> 有覆盖(被摄像头覆盖)
对 null 节点,应该设置为有覆盖状态。(用反证法证明)
思路:
优先从叶子节点往上遍历,在叶子节点的父节点放摄像头。
左右孩子四种情况:
- 左右孩子都是有覆盖 -> 父节点是无覆盖(不需要放摄像头)
- 左右孩子至少有 1 个无覆盖,另一个孩子状态不管 -> 父节点应该放摄像头
- 左右孩子至少有一个有摄像头(另一个孩子不是无覆盖,即条件 2 不满足的情况) -> 父节点是有覆盖状态(不需要放摄像头)
- 特殊情况:如果遍历完了,根节点还是无覆盖的情况,则根节点要放一个摄像头

其实一共有 6 种常规情况(2C3 + 3 = 6),上面第一种情况包含 1 种,第二种情况包含 3 种,第三种情况包含 2 种。已经全部覆盖到了。
class Solution {
int result = 0;
public int minCameraCover(TreeNode root) {
result = 0; // 养成好习惯,main 函数使用全局变量用前先初始化
if (traversal(root) == 0) { // 如果遍历完后根节点无覆盖,根节点额外放一个摄像头,对应情况 4
result++;
}
return result;
}
public int traversal(TreeNode root) {
// 0 -> 无覆盖(未被摄像头覆盖)
// 1 -> 有摄像头
// 2 -> 有覆盖(被摄像头覆盖)
if (root == null) {
return 2; // null 节点被视作有覆盖
}
// 左
int left = traversal(root.left);
// 右
int right = traversal(root.right);
// 中
if (left == 2 && right == 2) { // 左右孩子都有覆盖,父节点返回未覆盖
return 0;
}
if (left == 0 || right == 0) { // 左右孩子任意一个未覆盖,父节点放摄像头
result++;
return 1;
}
if (left == 1 || right == 1) { // 左右孩子任意一个有摄像头,另一个不是无覆盖,父节点返回有覆盖
return 2;
}
return -1; // 逻辑不会走到这里
}
}
309

被折叠的 条评论
为什么被折叠?



