leetcode-zgd-day36-435.无重叠区间/763.划分字母区间/56.合并区间

79 阅读2分钟

435.无重叠区间

题目链接:Loading Question... - 力扣(LeetCode)

解题思路:

首先是对数组进行排序,下面代码的解法是有问题的,想着对两个维度都进行排序,但是往往同时关注两个维度会顾此失彼,并不能够正确解题。

最初以为按照双维度进行排序之后,只要遇到重复的区间,删除后出现的区间即可,但是事实并非如此。当两个区间重叠的时候,应该删除的是区间右侧更大的区间,保留右边界更小的区间。

错误代码:

 class Solution {
     public int eraseOverlapIntervals(int[][] intervals) {
         // 对数组进行排序,先按1进行排序,再按2进行排序
         Arrays.sort(intervals,(a,b) -> Integer.compare(a[0],b[0]) == 0? Integer.compare(a[1],b[1]):Integer.compare(a[0],b[0]));
         int curend = intervals[0][1];
         int num = 0;
         for(int i = 1; i < intervals.length; i++){
             if(curend > intervals[i][0]){
                 num++; // 删除当前区间
                 curend = Math.min(curend,intervals[i][1]);
             }else{ // 当前区间和上一个区间没有重叠
                 curend = intervals[i][1];
             }
         }
         return num;
     }
 }

正确的代码:

删除的时候不能无脑删除右侧的数组。

 class Solution {
     public int eraseOverlapIntervals(int[][] intervals) {
         // 对数组进行排序,先按1进行排序,再按2进行排序
         Arrays.sort(intervals,(a,b) -> Integer.compare(a[0],b[0]));
         int curend = intervals[0][1];
         int num = 0;
         for(int i = 1; i < intervals.length; i++){
             if(curend > intervals[i][0]){
                 num++; // 删除重叠的两个区间的其中一个
                 curend = Math.min(curend,intervals[i][1]); // 删除右边更大的,保留右边更小的
             }else{ // 当前区间和上一个区间没有重叠
                 curend = intervals[i][1];
             }
         }
         return num;
     }
 }

763.划分字母区间

题目链接:763. 划分字母区间 - 力扣(LeetCode)

解题思路:

将26个字母所在的区间记录下来,然后就是合并区间,合并过后的区间计算各个区间长度即可。就是可以拆分的字母区间的长度。

 class Solution {
     public List<Integer> partitionLabels(String s) {
         List<Integer> ans = new ArrayList<>();
         // 该题的思路我感觉还是合并区间,只不过需要先统计每一个字母的区间
         int[][] record = new int[26][2];
         char[] schar = s.toCharArray();
         for(int i = 0; i < schar.length; i++){
             if(record[schar[i] - 'a'][0] == 0){
                 record[schar[i] - 'a'][0] = i;
             }
             record[schar[i] - 'a'][1] = i;
         }
         //第一个元素区别对待一下
         record[schar[0] - 'a'][0] = 0;
         Arrays.sort(record,(a,b)-> Integer.compare(a[0],b[0]));
         int startIndex = record[0][0], endIndex = record[0][1];
         for(int i = 1; i < record.length; i++){
             if(endIndex >= record[i][0]){
                 endIndex = Math.max(record[i][1], endIndex);
             }else{
                 ans.add(endIndex - startIndex + 1);
                 startIndex = record[i][0];
                 endIndex = record[i][1];
             }
         }
         ans.add(endIndex - startIndex + 1);
         return ans;
     }
 }

56.合并区间

题目链接:56. 合并区间 - 力扣(LeetCode)

解题思路:

该题目思路比较简单,先排序,然后当下一个非重叠区域出现的时候将上一个合并的重叠区域起始和终止位置插入结果数组即可。

 class Solution {
     public int[][] merge(int[][] intervals) {
         // 按照区间起点从小到大进行排序
         Arrays.sort(intervals,(a,b) -> Integer.compare(a[0],b[0]));
         // 创建一个数组来保存结果
         List<int[]> ans = new ArrayList<>();
         // 当前区间的起点和终点
         int startIndex = intervals[0][0], endIndex = intervals[0][1];
         for(int i = 1; i < intervals.length; i++){
             if(intervals[i][0] <= endIndex){
                 endIndex = Math.max(endIndex, intervals[i][1]);
             }else{
                 ans.add(new int[]{startIndex, endIndex});
                 startIndex = intervals[i][0];
                 endIndex = intervals[i][1];
             }
         }
         ans.add(new int[]{startIndex, endIndex});
         return ans.toArray(new int[0][]);
     }
 }