代码随想录算法训练营第三十六天 | 贪心算法 part 5 | 435. 无重叠区间、763.划分字母区间、56. 合并区间

目录

  • 435. 无重叠区间
    • 思路
    • 代码
    • 复杂度分析
  • 763.划分字母区间
    • 思路
    • 代码
    • 复杂度分析
  • 56. 合并区间
    • 思路
    • 代码
    • 复杂度分析

435. 无重叠区间

Leetcode

代码随想录算法训练营第三十六天 | 贪心算法 part 5 | 435. 无重叠区间、763.划分字母区间、56. 合并区间_第1张图片

思路

本题可以计算重叠的区间数量,也可以计算不重叠的区间数量。我采用的是计算重叠的区间数量。

具体的细节和452.用最少数量的箭引爆气球很相似。

  1. 首先对区间进行左排序
  2. 只要区间的左边界比前一个区间的右边界 小,那么便存在一个重叠区间
  3. 记录区间同时更新重叠区间的右边界

代码

class Solution:
    def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
        intervals.sort(key = lambda x : x[0])
        res = 0
        for i in range(1, len(intervals)):
            if intervals[i][0] >= intervals[i-1][1]:
                continue
            else:
                res += 1
                intervals[i][1] = min(intervals[i][1], intervals[i-1][1])

        return res

基于左边界 把452.用最少数量的箭引爆气球代码稍做修改

class Solution:
    def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
        if not intervals:
            return 0
        
        intervals.sort(key=lambda x: x[0])  # 按照左边界升序排序
        
        result = 1  # 不重叠区间数量,初始化为1,因为至少有一个不重叠的区间
        
        for i in range(1, len(intervals)):
            if intervals[i][0] >= intervals[i - 1][1]:  # 没有重叠
                result += 1
            else:  # 重叠情况
                intervals[i][1] = min(intervals[i - 1][1], intervals[i][1])  # 更新重叠区间的右边界
        
        return len(intervals) - result

复杂度分析

  • 时间复杂度:O(nlog n) ,有一个排序
  • 空间复杂度:O(1)

763.划分字母区间

Leetcode

代码随想录算法训练营第三十六天 | 贪心算法 part 5 | 435. 无重叠区间、763.划分字母区间、56. 合并区间_第2张图片

思路

在遍历的过程中相当于是要找每一个字母的边界,如果找到之前遍历过的所有字母的最远边界,说明这个边界就是分割点了。此时前面出现过所有字母,最远也就到这个边界了。

可以分为如下两步:

  1. 统计每一个字符最后出现的位置
  2. 从头遍历字符,并更新字符的最远出现下标,如果找到字符最远出现位置下标和当前下标相等了,则找到了分割点

如图:
代码随想录算法训练营第三十六天 | 贪心算法 part 5 | 435. 无重叠区间、763.划分字母区间、56. 合并区间_第3张图片

代码

class Solution:
    def partitionLabels(self, s: str) -> List[int]:
        distanceDict = {}

        for i in range(len(s)):
            distanceDict[s[i]] = i
        
        length = 0
        maxIndex = 0
        res = []
        for i in range(len(s)):
            length += 1
            maxIndex = max(maxIndex, distanceDict[s[i]])
            if i == maxIndex:
                res.append(length)
                length = 0
        
        return res

复杂度分析

  • 时间复杂度:O(n)
  • 空间复杂度:O(1),使用的hash数组是固定大小

56. 合并区间

Leetcode

代码随想录算法训练营第三十六天 | 贪心算法 part 5 | 435. 无重叠区间、763.划分字母区间、56. 合并区间_第4张图片

思路

思路和前面的题类似,使用相同的方法判断是否存在重叠的区间。

但是需要注意的是,因为我们不仅需要判断重叠区间,还需要合并重叠的区间,并且最后还要将它们返回,所以我们新建一个二维数组来帮助我们完成这项任务。

在最开始的时候,res直接放入intervals[0]来方便后续的比对。

这样的操作避免了以下难题:

  1. 如果第一个区间是不重叠区间,我们也能采用相同的逻辑将它放入res
  2. 直接在res上进行区间的合并,不需要将区间从res拿出来再放入。

代码

class Solution:
    def merge(self, intervals: List[List[int]]) -> List[List[int]]:
        if len(intervals) <= 1:
            return intervals
        intervals.sort(key = lambda x:x[0])
        res = [intervals[0]]

        for i in range(1, len(intervals)):
            if intervals[i][0] <= res[-1][1]:
                res[-1] = [res[-1][0], max(intervals[i][1], res[-1][1])]
            else:
                res.append(intervals[i])
        return res

复杂度分析

  • 时间复杂度: O(nlogn)
  • 空间复杂度: O(logn)

你可能感兴趣的:(代码随想录算法训练营,算法,贪心算法,数据结构,leetcode,python)