1 56. 合并区间
题目:以数组 intervals
表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi]
。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。
提示:
1 <= intervals.length <= 104
intervals[i].length == 2
0 <= starti <= endi <= 104
思路:本题与452,435相类似,都是对比区间数组,然后在此基础上修改区间范围。本题需要借助一个辅助集合记录新的区间数组。首先对区间数组进行排序,分别记录当前区间的起始和结束位置。当两个数组的区间有重叠时,修改记录的范围,直到新的数组不和当前记录重叠。将记录添加到辅助数组中。
注意:记录范围的变化,一定是取最大范围;区间数组在判断循环结束后,需要将最后一次记录的数据保存到辅助数组中。
Java实现
class Solution {
public int[][] merge(int[][] intervals) {
// 辅助数组保存新的区间数组
List<int[]> res = new LinkedList<>();
// 首先对数组进行排序,然后逐一比较重叠区间,将新区间加入到res中
Arrays.sort(intervals,(a,b)->Integer.compare(a[0],b[0]));
int start = 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{
res.add(new int[]{start,end});
start = intervals[i][0];
end = intervals[i][1];
}
}
// 剩余的最后一个区间数组添加到集合中
res.add(new int[]{start,end});
return res.toArray(new int[res.size()][]);
}
}
2 738. 单调递增的数字
题目:当且仅当每个相邻位数上的数字 x
和 y
满足 x <= y
时,我们称这个整数是单调递增的。
给定一个整数 n
,返回 小于或等于 n
的最大数字,且数字呈 单调递增 。
提示:
0 <= n <= 109
思路: 暴力遍历可以解答但是时间复杂度一定不满足要求。考虑到本题需要对每一位上的数进行比较,因此,将数首先转化为个位数的数组。其次,如果数组从前向后进行比较,那么每次修改后都要从头重新比较,因此,选择从末尾到开头遍历。现在开始考虑,如98,8<9即n[i]<n[i-1],此时对n[i-1]-1,将n[i]变为9,则此时一定满足n[i]>n[i-1]。再考虑如332,n[3]<n[2],则将332先变为329,仍不满足要求,此时n[2]<n[1],继续修改,此时为299,符合要求。更多位数的数以此类推。
注意:如332此类需要将多个数变为9,可以记录变9的位置,统一进行修改。
Java实现
class Solution {
public int monotoneIncreasingDigits(int n) {
String s = String.valueOf(n);
char[] chars = s.toCharArray();
int start = s.length(); // 标记变9的位置
for(int i=s.length()-2; i>=0; i--){
if(chars[i]>chars[i+1]){
chars[i]--;
start = i+1;
}
}
for(int i=start; i<s.length(); i++){
chars[i] = '9';
}
return Integer.parseInt(String.valueOf(chars));
}
}
3 968. 监控二叉树
题目:给定一个二叉树,我们在树的节点上安装摄像头。节点上的每个摄影头都可以监视其父对象、自身及其直接子对象。计算监控树的所有节点所需的最小摄像头数量。
提示:
- 给定树的节点数的范围是
[1, 1000]
。 - 每个节点的值都是 0。
思路:本题很难,博主只有一个粗略的思路,更加详细的解析还需移步学习 代码随想录-968.监控二叉树 本题要考虑监控到所有的节点,如果从根节点从上至下遍历,需要随着树的形状不断该改变相机位置,因此考虑从叶子节点开始从下至上遍历。考虑到相机可以覆盖上下中三层,如果将相机置于叶子结点会浪费一层,因此,相机会置于叶子结点的父节点上,然后根据覆盖情况依次向上。具体的覆盖情况可以参考解析。
注意:存在多种覆盖情况。
Java实现
/**
* 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 {
int res = 0;
// 覆盖状态:0-无覆盖;1-相机;2-覆盖
public int minCameraCover(TreeNode root) {
// 对根节点状态进行检查,防止根节点无覆盖
if(minCame(root)==0){
res++;
}
return res;
}
private int minCame(TreeNode root){
if(root==null){ // 叶子节点一定是被覆盖的
return 2;
}
// 后续遍历,从下至上判断
int left = minCame(root.left);
int right = minCame(root.right);
// 如果左右节点都覆盖了,那本节点状态未覆盖,且没有相机
if(left==2 && right==2){
return 0;
}else if(left==0 || right==0){
// 左右节点都是无覆盖状态,当前根节点应该设置相机
res++;
return 1;
}else{
return 2;
}
}
}