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

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

  • 一. 贪心相关算法题
    • 435.无重叠区间
      • 贪心
        • 思路
    • 763.划分字母区间
      • 贪心
        • 思路
    • 56.合并区间
      • 贪心
        • 思路

一. 贪心相关算法题

435.无重叠区间

贪心

思路

  • 将区间右边界从小到大排序,如果重叠优先保留边界小的,这样可以保证留给剩余区间的范围就大了
class Solution {
    public int eraseOverlapIntervals(int[][] intervals) {
        // 按照有边界排序,交叉时取有边界最小的,这样留给后面区间的范围就大了
        Arrays.sort(intervals, Comparator.comparingInt(a -> a[1]));
        int count = 0;
        int minRight = Integer.MIN_VALUE;
        for (int i = 0; i < intervals.length; i++) {
            // 如果有边界小于等于下一个的左边界说明无交集
            if (minRight<=intervals[i][0]){
                minRight = intervals[i][1];
            }else {
                count++; //有交集,且右边界大于当前最小右边界删除数加一
            }
        }
        return count;
    }
}

763.划分字母区间

贪心

思路

  • 将此题目转换理解为寻找每个字母所在的最大区间就很好理解了
  • 遍历每个字符,并不断更新保存每个字符最后出现的位置这个位置就是这个字符的最大区间,这里题目中明确字符全部由小写字母组成,可以定义固定长度的哈希表维护每个字符最后出现位置
  • 再次遍历字符并不断更新可能存入子区间的字符的最大值,
    • 子区间中字符最大值一定是区间最后一个字符所在的索引
    • 所以遍历字符串中当遍历到下标等于子区间中最大下标时这个子区间就是确定了
    • 记录当前子区间的长度
    • 至于为什么要等带下标指向当前区间最大值时才记录长度是因为遍历的过程中最大下标是有可能不断更新变化的
class Solution {
    public List<Integer> partitionLabels(String s) {
        //先遍历字符串统计字符最后出现的下标
        //然后根据最后出现的下标分割字符串
        int[] hash = new int[26]; //全小写字母,哈希表大小可以固定
        for (int i = 0; i < s.length(); i++) {
            hash[s.charAt(i) - 'a'] = i;
        }
        List<Integer> res = new ArrayList<>();
        int left = 0,maxRight = -1;
        for (int i = 0; i < s.length(); i++) {
            //取右边界最大值
            maxRight = Math.max(maxRight,hash[s.charAt(i)-'a']);
            if (i == maxRight){ //如果下标到达有边界最大值
                res.add(i-left+1); //记录区间长度
                left = i+1; //更新左边界
            }
        }
        return res;
    }
}

56.合并区间

贪心

思路

  • 先将数组左边界按照从小到大的顺序排序,然后遍历数组出现重叠的区间就合并,不重叠就记录
  • 因为判断不重叠才记录所以,每次判断到不重叠记录的是上一个处理完的区间
  • 所以在遍历完毕后要把最后一个区间也记录到返回数组中
class Solution {
    public int[][] merge(int[][] intervals) {
        
        Arrays.sort(intervals, Comparator.comparing(a->a[0]));
        List<int[]> list = new ArrayList<>();

        int lastStart = intervals[0][0],lastEnd = intervals[0][1];
        for (int i = 1; i < intervals.length; i++) {
            //重叠,合并
            if (!(intervals[i][0]>lastEnd)){

                lastEnd = Math.max(lastEnd,intervals[i][1]);
            }else {
                list.add(new int[]{lastStart,lastEnd}); //因为这里记录的是上一区间,所以在循环结束时还是要把最后一个区间记录
                lastStart = intervals[i][0];
                lastEnd = intervals[i][1];
            }
        }
        list.add(new int[]{lastStart,lastEnd});
        return list.toArray(new int[0][]);

    }
}

你可能感兴趣的:(代码随想录算法营,算法,贪心算法,leetcode,java,1024程序员节)