算法刷题打卡031 | 贪心算法5

今天的贪心算法题都跟区间相关,一般看到题目给出一些区间的列表,很自然会想到先排序便于判断和遍历。

LeetCode 435 无重叠区间

题目链接:435. 无重叠区间 - 力扣(Leetcode)

看到这题,很容易联想到前一天做的引爆气球的题目,同样对区间排序后做判断,对于重叠的区间只保留一个,和用一支箭引爆一堆重叠的气球异曲同工,只是要注意这里的区间端点相等也可以认为是不重叠的区间: 

class Solution:
    def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
        # 类似于452用最少数量的箭引爆气球,只要求出箭的数量n,需要移除的数量就是len(intervals) - n
        # 注意这里的区间不包含端点
        intervals.sort(key=lambda x: (x[0], x[1]))
        i = 0
        num = len(intervals)
        n = 0
        while i < num:
            left_end = intervals[i][1]
            j = i +1
            while j < num and intervals[j][0] < left_end:
                left_end = min(left_end, intervals[j][1])
                j += 1
            n += 1
            i = j
        return num - n

LeetCode 763 划分字母区间

题目链接:763. 划分字母区间 - 力扣(Leetcode)

 从区间的合并转变为区间的划分,一下子没转过弯来,思路就陷入了死胡同:每种字母只能出现在一个区间,必然需要知道每个字母出现的最右下标,但这个下标怎么用于划分区间?看力扣题解才感觉拨云见日(自己想是怎么也想不到的吧),遍历字符串的过程中,如果遇到当前下标==前面遍历中所有字母的最右下标,说明前面遍历过的字母都只存在于当前区间里,可以将这部分分出来了:

class Solution:
    def partitionLabels(self, s: str) -> List[int]:
        last_index = dict()  # 记录每个字母出现的最后一个位置的下标
        n = len(s)
        for i in range(n):
            last_index[s[i]] = i
        
        res = []
        start, end = 0, 0
        for i in range(n):
            end = max(end, last_index[s[i]])
            if i == end:
                res.append(end - start + 1)
                start = end + 1
        return res

LeetCode 56 合并区间 

题目链接:56. 合并区间 - 力扣(Leetcode)

 合并区间反而显得比较简单了,排序之后,不断将有重叠的区间吸收到当前的最左区间:

class Solution:
    def merge(self, intervals: List[List[int]]) -> List[List[int]]:
        intervals.sort(key=lambda x: (x[0], x[1]))
        res = []
        temp = intervals[0].copy()
        for i in range(1, len(intervals)):
            start, end = intervals[i]
            if start <= temp[1]:
                temp[1] = max(end, temp[1])  # 更新当前合并区间的右边界(排序后左边界保持递增)
            else:
                res.append(temp.copy())
                temp = [start, end]
        res.append(temp)
        return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值