前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >无重叠区间——贪心算法

无重叠区间——贪心算法

作者头像
用户8639654
修改2021-08-24 18:00:42
2570
修改2021-08-24 18:00:42
举报
文章被收录于专栏:云计算运维

给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。

注意:

  • 可以认为区间的终点总是大于它的起点。
  • 区间 [1,2] 和 [2,3] 的边界相互“接触”,但没有相互重叠。

示例 1:

输入: [ [1,2], [2,3], [3,4], [1,3] ] 输出: 1

解释: 移除 [1,3] 后,剩下的区间没有重叠。

示例 2:

输入: [ [1,2], [1,2], [1,2] ] 输出: 2

解释: 你需要移除两个 [1,2] 来使剩下的区间没有重叠。

示例 3:

输入: [ [1,2], [2,3] ] 输出: 0

解释: 你不需要移除任何区间,因为它们已经是无重叠的了。

题解:又是给了一组数组,问之间有无重叠区间,显然可以考虑将其排序之后,逐个比较,考虑局部最优解,符合贪心算法思想

因为区间的终点始终大于它的起点,我们考虑将其按照终点大小,由小到大排序

这里直接调用Arrays.sort()进行排序,以下为Lambda表达式写法

Arrays.sort(intervals, new Comparator<int[]>() { public int compare(int[] interval1, int[] interval2) { return interval1[1] - interval2[1]; } });

这里重写了compare方法,interval1[1] - interval2[1],即由小到大interval1[1] < interval2[1]进行排序

简化版Lambda写法:

Arrays.sort(intervals,(o1,o2) -> o1[1] < o2[1]);

排完序后我们考虑:依次从最左边区间的右边界和下一区间的左边界比较

int count = 0, prev = intervals[0][1]; for(int i = 1;i < n;i++ ){ if(prev > intervals[i][0]) count++; else prev = intervals[i][1]; }

若右边界大于左边界,则说明区间重叠,需移除一个,再和下一区间左边界比较,此时count++;

若小于等于,则说明,区间无重叠,这时取到下一区间的右边界,向右递进,再和下下区间的左边界进行比较,直至到达数组末尾。

Java代码:

代码语言:javascript
复制
class Solution {
    public int eraseOverlapIntervals(int[][] intervals) {
        if (intervals.length == 0)
            return 0;
        Arrays.sort(intervals, new Comparator<int[]>() {
            public int compare(int[] interval1, int[] interval2) {
                return interval1[1] - interval2[1];
            }
        });
        int count = 0, prev = intervals[0][1];
        for(int i = 1;i < intervals.length;i++){
            if(prev > intervals[i][0]) count++;
            else prev = intervals[i][1];
        }
    return count;
    }
}

C++:

代码语言:javascript
复制
class Solution {
public:
    int eraseOverlapIntervals(vector<vector<int>>& intervals) {
            if (intervals.empty()) {
            return 0;
            }
        int n = intervals.size();
        sort(intervals.begin(), intervals.end(), [](vector<int> a, vector<int> b) {
        return a[1] < b[1];
        });
        int count = 0, prev = intervals[0][1];
        for(int i = 1;i < n;i++ ){
            if(prev > intervals[i][0])
                count++;
            else 
            prev = intervals[i][1];
        }
        return count;
    }
};

这是一个Medium难度题,但当我们思考其特征(给了一组数组数据,区间重叠是局部问题,且没有后效性),发现符合贪心算法,接着找出贪心策略(即排序后依次比较),我们发现此题还是可以简洁性的处理。

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档