LeetCode刷题day36|435. 无重叠区间、763.划分字母区间、56. 合并区间

一、435. 无重叠区间

主要思路:

  1. 依据左边界对所有区间排序
  2. 对区间进行遍历,如果当前区间的左边界大于等于 right值,则不会重叠,right值更新为当前区间的右边界。否则,进入下一步。
  3. 如果当前区间的右边界大于right值,则删除当前区间,并进入下一个循环(不需要更新right值)。否则,需要将前一个区间删除,同时将right值更新为当前区间的右边界。

以下是代码部分:

public class 无重叠区间435 {

    //思路:先依据左点排序,
    public int eraseOverlapIntervals(int[][] intervals) {

        Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0]));

        int right = intervals[0][1];

        int res = 0;

        for (int i = 1; i < intervals.length; i++) {

            //如果当前的区间左端点小于上个区间右端点(有重合)
            if( intervals[i][0] < right){

                //有重合且当前区间右端点大于前一个区间,直接删除
                if( intervals[i][1] > right){
                    res++;
                    //不需要更新right,直接下一轮
                    continue;
                }else {
                    //小于前一个区间的右端点,则删除前一个区间
                    res++;
                }
            }

            //更新right
            right = intervals[i][1];
        }
        return res;
    }
}

二、763.划分字母区间

主要思路:

  1. 首先记录每个字母出现的最大下标位置。
  2. 遍历一遍数组,将数组分为题目要求的一个个区间。max记录区间所有字母中最后出现的那个字母的下标。
  3. 在遍历的过程中更新max值,如果当前遍历的位置i 与max相等,则说明区间中的字母都找完了,之后不会再出现了。
  4. 重复第3步,直到遍历完所有元素。

以下是代码部分:

public class 划分字母区间763 {
	//简化后的代码
    public List<Integer> partitionLabels2(String s) {

        int[] index = new int[26];

        for (int i = 0; i < s.length(); i++) {
            //更新每个字母的最右边下标
            index[s.charAt(i) - 'a'] = i;
        }

        List<Integer> res = new ArrayList<>();
        int tmp = 0;
        //当前区间的最优边界
        int max = 0;

        for (int i = 0; i < s.length(); i++) {

            //更新max在前边,有利于让第0个节点与其他节点统一处理
            max = Math.max(max, index[s.charAt(i) - 'a']);
            tmp++;

            //判断是否到区间最优边界
            if( i == max){
                res.add(tmp);
                tmp = 0;
            }
        }
        return res;
    }
}

三、56. 合并区间

这道题其实与第一道题很像,思路基本差不多。
主要思路:

  1. 依据左边界排序
  2. 遍历数组,分成一块块大区间,其中 tmp[0] 记录大区间的左边界,tmp[1] 记录大区间的右边界。
  3. 在遍历的过程中,tmp[0] 只在开启下一个大区间时更新,而 tmp[1] 则是取当前大区间的最大右边界。
  4. 如果当前小区间大于 tmp[1],说明合不到一块了,就开启下一个新的大区间。
  5. 最后,注意把最后一个大区间加入结果集中(for循环中没有记录最后一个)。

以下是代码部分:

public class 合并区间56 {

    public int[][] merge(int[][] intervals) {

        Arrays.sort(intervals, (a, b) -> a[0] - b[0]);

        List<int[]> res = new ArrayList<>();
        int[] tmp = new int[2];

        tmp[0] = intervals[0][0];
        int right = intervals[0][1];

        for (int i = 1; i < intervals.length; i++) {

            //如果当前的左边界大于上个局部区间的右边界,则分开
            if( intervals[i][0] > right){
                //更新右区间,收集结果
                tmp[1] = right;
                /*
                //需要new一个对象加入到res
                int[] p = new int[2];
                p[0] = tmp[0];
                p[1] = tmp[1];
                res.add(p);

                 */
                res.add(new int[]{tmp[0], tmp[1]});

                //更新新的左边界
                tmp[0] = intervals[i][0];
            }
            //加入到前一个区间,更新right
            right = Math.max(right, intervals[i][1]);
        }

        //由于都是在收集上个区间的结果,所以最后一个区间没有收集到。收集最后一个区间的结果
        tmp[1] = right;
        res.add(tmp);

        //踩坑:超出时间限制。
        return res.toArray(new int[res.size()][2]);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值