返回

LeetCode HOT 100:合并区间背后的微妙细节

前端

前言

LeetCode 作为算法题练习平台,其 HOT 100 题目无疑是备受关注的经典之作。本篇文章将聚焦于其中的“合并区间”这一中等难度的题目,带领大家深入剖析其背后蕴藏的微妙细节。

题目概述

“合并区间”问题如下:

给定一个由区间组成的列表,每个区间表示一个时间段的开始和结束时间。合并所有重叠的区间,返回合并后的区间列表。

例如:

输入:[[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]

贪心算法

贪心算法是一种逐步做出局部最优选择,期望最终获得全局最优解的算法。对于本题而言,贪心算法的思路为:

  1. 对区间按照开始时间排序。
  2. 遍历排序后的区间列表,将每个区间与上一个区间比较:
    • 如果两个区间重叠,则合并这两个区间。
    • 否则,将当前区间添加到结果列表中。

以下为 Python 实现:

def merge_intervals(intervals):
    # 对区间按开始时间排序
    intervals.sort(key=lambda x: x[0])

    merged_intervals = []
    for interval in intervals:
        # 如果结果列表为空或当前区间与上一个区间不重叠
        if not merged_intervals or merged_intervals[-1][1] < interval[0]:
            merged_intervals.append(interval)
        # 否则,与上一个区间合并
        else:
            merged_intervals[-1][1] = max(merged_intervals[-1][1], interval[1])

    return merged_intervals

排序与双指针

排序与双指针的解法与贪心算法类似,但具体实现方式有所不同:

  1. 对区间按照开始时间排序。
  2. 使用两个指针 left 和 right,left 指向当前考察的区间,right 指向与 left 重叠的区间。
  3. 当 left 和 right 指向的区间重叠时,更新 right 指向的区间为两个区间的合并区间。
  4. 当 left 指向的区间与 right 指向的区间不再重叠时,将 left 指向的区间添加到结果列表中,并将 left 和 right 指向下一个区间。

以下为 Python 实现:

def merge_intervals(intervals):
    # 对区间按开始时间排序
    intervals.sort(key=lambda x: x[0])

    merged_intervals = []
    left, right = 0, 1

    while right < len(intervals):
        if intervals[left][1] >= intervals[right][0]:
            # 合并区间
            intervals[left][1] = max(intervals[left][1], intervals[right][1])
            right += 1
        else:
            # 添加非重叠区间
            merged_intervals.append(intervals[left])
            left = right

    # 添加最后一个区间
    merged_intervals.append(intervals[left])

    return merged_intervals

总结

通过探索贪心算法和排序与双指针两种解法,我们可以看到,看似简单的算法题往往蕴藏着丰富的细节和多种可行的解法。每一种解法都有其优缺点,掌握不同的解法有助于我们解决更复杂的问题。

本文旨在深入挖掘“合并区间”问题的精髓,帮助读者理解算法题的内涵,培养解决问题的能力。无论是初学者还是算法高手,都能从中学到有价值的经验和见解。