LeetCode算法刷题(python) Day38|08贪心算法|435. 无重叠区间、763.划分字母区间、56. 合并区间

LeetCode 435. 无重叠区间

力扣题目链接
本题与区间调度问题类似,找到最多的互不相交区间之后,剩余的区间就是要移除区间的最小数量。

class Solution:
    def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
        if not intervals: return 0
        # 按 end 升序排序
        intervals.sort(key=lambda x: x[1])
        # 至少有一个区间不相交
        count = 1
        # 排序后第一个区间是x
        x_end = intervals[0][1]
        for i in range(1, len(intervals)):
            if intervals[i][0] >= x_end:
                # 找到下一个区间了
                count += 1
                x_end = intervals[i][1]
        
        return len(intervals) - count

区间调度问题(Interval Scheduling)

问题描述:给你很多形如[start, end]的闭区间,请你设计一个算法,算出这些区间中最多有几个互不相交的区间。
举个例子,intvs = [[1,3], [2,4], [3,6]],这些区间最多有 2 个区间互不相交,即 [[1,3], [3,6]],你的算法应该返回 2。注意边界相同并不算相交。

正确的思路其实很简单,可以分为以下三步:

  1. 从区间集合 intvs 中选择一个区间 x,这个 x 是在当前所有区间中结束最早的(end 最小)。
  2. 把所有与 x 区间相交的区间从区间集合 intvs 中删除。
  3. 重复步骤 1 和 2,直到 intvs 为空为止。之前选出的那些 x 就是最大不相交子集。

LeetCode 763.划分字母区间

力扣题目链接

我的思路:先统计出每个字母的索引区间,然后就是区间调度问题,寻找一些互不相交的区间
在这里插入图片描述

class Solution:
    def partitionLabels(self, s: str) -> List[int]:
        record = dict()
        for i in range(len(s)):
            if s[i] not in record.keys():
                record[s[i]] = [i, i]
            else:
                record[s[i]][1] = i
        result = [0]
        intervals = [x for x in record.values()]
        x_end = intervals[0][1]
        curSum = 0
        
        for i in range(1, len(intervals)):
            if intervals[i][0] >= x_end:
                result.append(x_end - curSum + 1)
                curSum += result[-1]
                x_end = intervals[i][1]
            else:
                x_end = max(x_end, intervals[i][1])
        
        if sum(result) < len(s):
            result.append(len(s) - sum(result))
        return result[1:]

LeetCode 56. 合并区间

力扣题目链接

区间合并问题,与上一题类似

class Solution:
    def merge(self, intervals: List[List[int]]) -> List[List[int]]:
        intervals.sort(key=lambda x: (x[0], x[1]))
        
        result = []
        x_start = intervals[0][0]
        x_end = intervals[0][1]
        
        for i in range(1, len(intervals)):
            if intervals[i][0] <= x_end:
                x_end = max(x_end, intervals[i][1])
            else:
                result.append([x_start, x_end])
                x_start = intervals[i][0]
                x_end = intervals[i][1]
        
        result.append([x_start, x_end])
        return result

# 解法二:
class Solution:
    def merge(self, intervals):
        result = []
        if len(intervals) == 0:
            return result  # 区间集合为空直接返回

        intervals.sort(key=lambda x: x[0])  # 按照区间的左边界进行排序

        result.append(intervals[0])  # 第一个区间可以直接放入结果集中

        for i in range(1, len(intervals)):
            if result[-1][1] >= intervals[i][0]:  # 发现重叠区间
                # 合并区间,只需要更新结果集最后一个区间的右边界,因为根据排序,左边界已经是最小的
                result[-1][1] = max(result[-1][1], intervals[i][1])
            else:
                result.append(intervals[i])  # 区间不重叠

        return result

今日毕!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值