LeetCode 打卡day36--重叠区间, 合并区间, 划分字母区间


知识总结

区间题目三道题


Leetcode 435. 无重叠区间

题目链接

题目说明

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

在这里插入图片描述

代码说明

这道题和上一个射气球的题目很相似, 都是要先按照左端点排序, 然后找重叠区间中右端最小的为新的边界.

class Solution {
    
    
    public int eraseOverlapIntervals(int[][] intervals) {
    
    
        if(intervals.length <= 1) return 0;
        // Arrays.sort(intervals, (a1, a2) -> a1[0] - a2[0]);
        Arrays.sort(intervals, new Comparator<int[]>(){
    
    
            public int compare(int[] a1, int[] a2){
    
    
                return a1[0] - a2[0];
            }
        });
        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;
    }
}

Leetcode 763. 划分字母区间

题目链接

题目说明

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

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

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

在这里插入图片描述

代码说明

方法一
使用Map记录每个字母的最远距离.
count 记录还未达到 pre之前一共遍历了多少个字母.

class Solution {
    
    
    public List<Integer> partitionLabels(String s) {
    
    
        Map<Character, Integer> map = new HashMap<>();
        for(int i = 0; i < s.length(); i++){
    
    
            map.put(s.charAt(i), i);
        }
        List<Integer> res = new LinkedList<>();
        int pre = 0, count = 0;
        for(int i =0; i < s.length(); i++){
    
    
            int farIndex = map.get(s.charAt(i));
            if(i <= pre){
    
    
                count++;
            }else{
    
    
                res.add(count);
                count = 1;
            }
            pre = Math.max(pre, farIndex);

        }
        res.add(count);
        return res;
    }
}

方法2
使用数组代替map, 效率更高
当i == farIndex, 说明来到了一个小段的尽头, 添加新的长度到结果中

class Solution {
    
    
    public List<Integer> partitionLabels(String s) {
    
    
        List<Integer>list=new LinkedList<>();
        int[] edge=new int[26]; //每个位置代表一个字母
        char[] chars=s.toCharArray();
        for(int i=0;i<chars.length;i++){
    
    
            //变量数组,把每个字符出现的最远位置记录在edge中
            edge[chars[i]-'a']=i;
        }
        int idx=0;
        int last=-1;
        for(int i=0;i<chars.length;i++){
    
    
            //找到字符出现的最远边界
            idx=Math.max(idx,edge[chars[i]-'a']);
            if(i==idx){
    
    
                list.add(i-last);
                //记录起始位置
                last=i;
            }
        }
        return list;
    }
}

Leetcode 56. 合并区间

题目链接

题目说明

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

在这里插入图片描述

代码说明

class Solution {
    
    
    public int[][] merge(int[][] intervals) {
    
    
        if(intervals.length <= 1) return intervals;
        Arrays.sort(intervals, (a1, a2) -> (a1[0] - a2[0]));

        LinkedList<int[]> res = new LinkedList<>();
        res.add(intervals[0]);
        for(int i = 1; i < intervals.length; i++){
    
    
            if(intervals[i][0] <= res.getLast()[1]){
    
    
                res.getLast()[1] = Math.max(res.getLast()[1], intervals[i][1]);
            } else{
    
    
                res.add(intervals[i]);
            }
        }

        return res.toArray(new int[res.size()][]);
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_45872648/article/details/131207976