【算法36天:Day36】第八章贪心算法 合并区间(56)

107 阅读1分钟

题目三:

image.png

思路

大家应该都感觉到了,此题一定要排序,那么按照左边界排序,还是右边界排序呢?

都可以!

那么我按照左边界排序,排序之后局部最优:每次合并都取最大的右边界,这样就可以合并更多的区间了,整体最优:合并所有重叠的区间。

局部最优可以推出全局最优,找不出反例,试试贪心。

那有同学问了,本来不就应该合并最大右边界么,这和贪心有啥关系?

有时候贪心就是常识!哈哈

按照左边界从小到大排序之后,如果 intervals[i][0] < intervals[i - 1][1] 即intervals[i]左边界 < intervals[i - 1]右边界,则一定有重复,因为intervals[i]的左边界一定是大于等于intervals[i - 1]的左边界。

即:intervals[i]的左边界在intervals[i - 1]左边界和右边界的范围内,那么一定有重复!

这么说有点抽象,看图:(注意图中区间都是按照左边界排序之后了

56.合并区间

知道如何判断重复之后,剩下的就是合并了,如何去模拟合并区间呢?

其实就是用合并区间后左边界和右边界,作为一个新的区间,加入到result数组里就可以了。如果没有合并就把原区间加入到result数组。

代码如下:

var merge = function(intervals) {
    intervals.sort((a, b) => {
        if (a[0] != b[0]) {
            return a[0] - b[0]
        } else {
            return a[1] - b[1]
        }
    })
    let pre = intervals[0]
    let result = []
    for (let i = 1; i < intervals.length; i++) {
        console.log(pre)
        let cur = intervals[i]
        if (cur[0] > pre[1]) { // 不相交
            result.push(pre)
            pre = cur
        } else { // 相交
            pre[1] = Math.max(cur[1], pre[1])
        }
    }
    result.push(pre)
    return result
};