代码随想录算法训练营day36|无重叠区间、划分字母区间、合并区间

2023.4.19 无重叠区间

435. 无重叠区间 - 力扣(LeetCode)

这道题和引爆气球有点类似,我们需要找到重叠的区间,将其删去。先根据start进行排序,随后找出当前区间的左边起点在前一个区间的end之内的区间就是重叠区间,即我们需要删除的区间。

第一版代码

class Solution {
    public int eraseOverlapIntervals(int[][] intervals) {
        Arrays.sort(intervals,new Comparator<int[]>(){
            public int compare(int[] a,int[] b){
                if(a[0] != b[0]){
                    return a[0]-b[0];
                }
                else{
                    return a[1]-b[1];
                }
            }
        });
        int count = 0;
        for(int i = 1;i<intervals.length;i++){
            if(intervals[i][0]<intervals[i-1][1]){//发生重叠
            count++;
            //由于需要移除区间,所以我们要更新右边界
            intervals[i][1] = intervals[i-1][1];
            }
        }
        return count;
    }
}

错误原因,我们更新右边界时,不能直接选择上一个边界,因为有可能当前边界的右边界更小,我们需要选择更小的那个边界,这样才能获取的最少的删除区间数目。

class Solution {
    public int eraseOverlapIntervals(int[][] intervals) {
        Arrays.sort(intervals,new Comparator<int[]>(){
            public int compare(int[] a,int[] b){
                if(a[0] != b[0]){
                    return a[0]-b[0];
                }
                else{
                    return a[1]-b[1];
                }
            }
        });
        int count = 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][1],intervals[i][1]);
            }
        }
        return count;
    }
}

2023.4.19 划分字母区间

763. 划分字母区间 - 力扣(LeetCode)

如何保证同一个字母只在一个片段中?使用lastIndexOf来判断。

我们使用双重循环,外层循环对整个字符串进行遍历,内层循环来更新片段的长度,

使用一个boolean数组来判断当前元素是否已经判断过了。

自己AC了。。

class Solution {
    public List<Integer> partitionLabels(String s) {
        List<Integer> res = new ArrayList<>();
        boolean[] isRead = new boolean[26];
        int start = 0;
        boolean index = true;
        while(index){
            int end = s.lastIndexOf(s.charAt(start));
            isRead[s.charAt(start) - 'a'] = true;
            for(int j = start + 1;j<end;j++){
                if(isRead[s.charAt(j) - 'a']){//当前字符已经遍历过了
                    continue;
                }else{//当前字符还没有遍历过
                    isRead[s.charAt(j) - 'a'] = true;
                    int newEnd = s.lastIndexOf(s.charAt(j));
                    end = Math.max(end,newEnd);//更新右边界。
                }
            }
            //结束内层循环,返回长度。
            res.add(end-start+1);
            if(end == s.length()-1){
                break;
            }
            //更新起始位置
            start = end+1;
        }
        return res;
    }
}

2023.4.19 合并区间

56. 合并区间 - 力扣(LeetCode)

按照start其从小到大排序

然后判断是否重叠,如果重叠,更新边界,继续判断,如果不重叠,记录进结果中

            public int compare(int[] a,int[] b){
                    return a[0]-b[0];
            }
        });
        List<int[]> res = new ArrayList<>();
        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{//区间没有重叠,我们可以输出一个前一个的不重叠区间数组了。
                int[] temp = {start,end};
                res.add(temp);
                //更新start和end
                start = intervals[i][0];
                end = intervals[i][1];
            }
        }
        //注意,当i遍历到最后一个元素时,如果发生了重叠,此时会退出循环,不会进入else语句,所以当退出循环后我们还需要多进行一次add操作。
        //最后一次add
        int[] lastTemp = {start,end};
        res.add(lastTemp);
        return res.toArray(new int[res.size()][]);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值