代码随想录算法训练营第三十六天 | 435. 无重叠区间 763.划分字母区间 56. 合并区间

435. 无重叠区间

给定一个区间的集合 intervals,其中 intervals[i] = [starti, endi]。返回需要移除区间的最小数量,使剩余区间互不重叠 。

输入: intervals = [[1,2],[2,3],[3,4],[1,3]]
输出: 1
解释: 移除 [1,3] 后,剩下的区间没有重叠。

这道题需要我们求重叠区间,然后记录重叠区间就可以了

解题思路:

  1. 设置count用来记录重叠区间
  2. 将数组按照左边从小到大进行排序
  3. 如果intervals[i][0]<intervals[i-1][1] 说明i数组和i-1数组重叠,将count++ 记录重叠区间,然后保留最小右边界
class Solution {
    public int eraseOverlapIntervals(int[][] intervals) {
        int count=0;
        Arrays.sort(intervals,(a,b)->Integer.compare(a[0],b[0]));
        for(int i=1;i<intervals.length;i++){
            if(intervals[i][0]<intervals[i-1][1]){  //重叠情况
                count++;
                intervals[i][1]=Math.min(intervals[i][1],intervals[i-1][1]);
            }
        }
        return count;
    }
}

763. 划分字母区间

给你一个字符串 s 。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。

注意,划分结果需要满足:将所有划分结果按顺序连接,得到的字符串仍然是 s 。

返回一个表示每个字符串片段的长度的列表。

输入:s = "ababcbacadefegdehijhklij"
输出:[9,7,8]
解释:
划分结果为 "ababcbaca"、"defegde"、"hijhklij" 。
每个字母最多出现在一个片段中。
像 "ababcbacadefegde", "hijhklij" 这样的划分是错误的,因为划分的片段数较少。

这道题的关键是找到分割点

解题思路:

  1. 设置一个长度为27的数组,26个字母
  2. 遍历字符串,将每个字符最后出现的位置记录到数组当中hash[s.charAt(i)-'a']=i;
  3. 字母的最远下标就是分割点,可以记录下来,并需要一个left结点定义开始分割的起点right=Math.max(right,hash[s.charAt(i)-'a']);
class Solution {
    public List<Integer> partitionLabels(String s) {
        List<Integer> reslut=new ArrayList<>();
        int[] hash=new int[27];
        //将每个字符最后出现的位置
        for(int i=0;i<s.length();i++){
            hash[s.charAt(i)-'a']=i;
        }
        int left=0;
        int right=0;
        for(int i=0;i<s.length();i++){
            right=Math.max(right,hash[s.charAt(i)-'a']);
            if(i==right){  //找到分割点
                reslut.add(right-left+1);
                left=i+1;
            }
        }
        return reslut;
    }
}

56. 合并区间

以数组 intervals表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi]。请你合并所有重叠的区间,并返回一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间。

输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].

这道题的思路比较简单,就是需要找到重叠区间,然后将前一个区间的左区间,后后一个区间的右区间相连接构成结果,但是实际操作起来还是有些许复杂。

解题思路:

  1. 定义一个list用来添加结果,后续还需要转换成int[][]输出

  2. 将数组按照左边从小到大排序

  3. 定义左边界和右边界,之后循环就可以从1开始

  4. 遍历数组

    如果发现数组是重合的即intervals[i][0]≤intervals[i-1][1] 我们需要去更新最大的右边界right=Math.max(right,intervals[i][1]);

    如果发现数组接下来是不重叠,我们需要将前面求出的最小左边界和最大右边界添加到结果当中

    然后更新左边界和右边界

  5. 将剩余的数组添加到结果当中

  6. 最后需要将list转换为数组进行返回 reslut.toArray(new int[reslut.size()][]);

class Solution {
    public int[][] merge(int[][] intervals) {
        List<int[]> reslut=new ArrayList<>();
        //排序
        Arrays.sort(intervals,(a,b)->Integer.compare(a[0],b[0]));
        int start=intervals[0][0];   //左边界
        int right=intervals[0][1];   //右边界
        for(int i=1;i<intervals.length;i++){
            if(intervals[i][0]>right){     //返现区间没有继续重叠相连
                reslut.add(new int[]{start,right});   //按照最大左边界和右边界将其添加到结果中
                start=intervals[i][0];   //更新左边界和右边界
                right=intervals[i][1];
            }else{   //发现区间重合去更新最大右边界
                right=Math.max(right,intervals[i][1]);
            }
        }
        reslut.add(new int[]{start,right});    //把最后剩余的添加进来
        return reslut.toArray(new int[reslut.size()][]);

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值