跟着甜姨整理了这一类问题,没有固定套路,但需要找规律以及细心。
重叠区间
252,会议室,easy

题解
实质是判断有没有重叠区间,将区间按照会议开始时间排序,然后遍历一遍即可。
代码
class Solution{ public boolean canAttendMeetings(int[][] intervals){ Arrays.sort(intervals, (v1, v2)->v1[0]-v2[0]); for(int i = 1; i < intervals.length; i++){ if(intervals[i][0] < intervals[i - 1][1]) return false; } return true; } }
|
56,合并区间,medium

题解
与上一题的区别在于要合并重叠的区间,还是从intervals的第一个元素开始遍历,最开始比较的对象为intervals[0][1]
,在遍历过程中不断更新,此对象的含义为上一个区间的末尾。即新的区间的开头比上一区间的末尾大,就不需要合并。
代码
class Solution { public int[][] merge(int[][] intervals) { if(intervals.length == 1) return intervals; Arrays.sort(intervals, (v1, v2) -> v1[0] - v2[0]); int flag = intervals[0][1]; int[][] res = new int[intervals.length + 1][2]; int idx = 0; res[0] = intervals[0]; for(int i = 1; i < intervals.length; i++){ if(intervals[i][0] <= flag){ res[idx][1] = Math.max(res[idx][1], intervals[i][1]); flag = res[idx][1]; }else{ res[++idx] = intervals[i]; flag = intervals[i][1]; } } return Arrays.copyOf(res, idx + 1); } }
|
57,插入区间,medium

题解
本题中的区间已经按照起始端点升序排列,因此我们直接遍历区间列表,寻找新区间的插入位置即可。具体步骤如下:
- 首先将新区间左边且相离的区间加入结果集(遍历时,如果当前区间的结束位置小于新区间的开始位置,说明当前区间在新区间的左边且相离);
- 接着判断当前区间是否与新区间重叠,重叠的话就进行合并,直到遍历到当前区间在新区间的右边且相离,将最终合并后的新区间加入结果集;
- 最后将新区间右边且相离的区间加入结果集。
代码
class Solution { public int[][] insert(int[][] intervals, int[] newInterval) { int pL = newInterval[0]; int pR = newInterval[1]; int[][] res = new int[intervals.length + 1][2]; int i = 0; int idx = 0; while(i < intervals.length && intervals[i][1] < pL){ res[idx++] = intervals[i++]; } while(i < intervals.length && intervals[i][0] <= pR){ pL = Math.min(intervals[i][0], pL); pR = Math.max(intervals[i][1], pR); i++; } res[idx++] = new int[]{pL, pR}; while(i < intervals.length){ res[idx++] = intervals[i++]; } return Arrays.copyOf(res, idx); } }
|
1288,删除被覆盖区间,medium

题解
贪心
先按区间左边界升序排列,如果相等,按右区间降序排列(消除覆盖区间)
这样只需要更新一个右边界值即可
遍历区间,如果被覆盖,区间数-1;如果没有被覆盖,则更新新的边界值。
代码
class Solution { public int removeCoveredIntervals(int[][] intervals) { if(intervals.length == 1) return 1; Arrays.sort(intervals, (v1, v2) -> v1[0] == v2[0] ? v2[1] - v1[1] : v1[0] - v2[0]); int res = intervals.length; int r = intervals[0][1]; for(int i = 1; i < intervals.length; i++){ if(intervals[i][1] <= r){ res--; } else r = Math.max(r, intervals[i][1]); } return res; } }
|
228,汇总区间,easy

题解
对连续的数字按固定格式输出,那么双指针找到不连续的数字即可。
找到之后更新i = j + 1
。
在一个循环中判断一下双指针所指位置,如果相同则只添加一个元素。
代码
class Solution { public List<String> summaryRanges(int[] nums) { List<String> res = new ArrayList<>(); if(nums.length == 0) return res; if(nums.length == 1){ res.add(String.valueOf(nums[0])); return res; } int i = 0; for(int j = 0; j < nums.length; j++){ if(j == nums.length - 1 || nums[j] + 1 != nums[j + 1]){ String tmp = String.valueOf(nums[i]) + "->" + String.valueOf(nums[j]); if(nums[i] != nums[j]) res.add(tmp); else res.add(String.valueOf(nums[j])); i = j + 1; } } return res; } }
|