LeetCode_day36-37 贪心

文章探讨了如何合并和处理区间问题,包括无重叠区间的消除和字母区间的划分。同时介绍了如何在二叉树中最小化摄像头的使用来覆盖所有节点,以及寻找单调递增的数字方法。这些是典型的计算机科学中的数据结构和算法问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

day36   56、435、736

# 56. 合并区间
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
# 435. 无重叠区间

# 基于左边界
class Solution:
    def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
        if not intervals:
            return 0

        intervals.sort(key=lambda x: x[0])  # 按照左边界升序排序
        count = 0  # 记录重叠区间数量

        for i in range(1, len(intervals)):#遍历所有区间
            if intervals[i][0] < intervals[i - 1][1]:  # 存在重叠区间  当前区间左边界和上一个区间左边界有所重叠
                intervals[i][1] = min(intervals[i - 1][1], intervals[i][1])  # 更新重叠区间的右边界
                count += 1

        return count
# 763.划分字母区间

# 版本1
class Solution:
    def partitionLabels(self, s: str) -> List[int]:
        last_occurrence = {}  # 存储每个字符最后出现的位置
        for i, ch in enumerate(s):
            last_occurrence[ch] = i

        result = []
        start = 0
        end = 0
        for i, ch in enumerate(s):
            end = max(end, last_occurrence[ch])  # 找到当前字符出现的最远位置
            if i == end:  # 如果当前位置是最远位置,表示可以分割出一个区间
                result.append(end - start + 1)
                start = i + 1

        return result

day37  738、968

# 968.监控二叉树

class Solution:


# Greedy Algo:
# 从下往上安装摄像头:跳过leaves这样安装数量最少,局部最优 -> 全局最优
# 先给leaves的父节点安装,然后每隔两层节点安装一个摄像头,直到Head
# 0: 该节点未覆盖
# 1: 该节点有摄像头
# 2: 该节点有覆盖
def minCameraCover(self, root: TreeNode) -> int:
    # 定义递归函数
    result = [0]  # 用于记录摄像头的安装数量
    if self.traversal(root, result) == 0:
        result[0] += 1

    return result[0]


def traversal(self, cur: TreeNode, result: List[int]) -> int:
    if not cur:
        return 2

    left = self.traversal(cur.left, result)
    right = self.traversal(cur.right, result)

    # 情况1: 左右节点都有覆盖
    if left == 2 and right == 2:
        return 0

    # 情况2:
    # left == 0 && right == 0 左右节点无覆盖
    # left == 1 && right == 0 左节点有摄像头,右节点无覆盖
    # left == 0 && right == 1 左节点无覆盖,右节点有摄像头
    # left == 0 && right == 2 左节点无覆盖,右节点覆盖
    # left == 2 && right == 0 左节点覆盖,右节点无覆盖
    if left == 0 or right == 0:
        result[0] += 1
        return 1

    # 情况3:
    # left == 1 && right == 2 左节点有摄像头,右节点有覆盖
    # left == 2 && right == 1 左节点有覆盖,右节点有摄像头
    # left == 1 && right == 1 左右节点都有摄像头
    if left == 1 or right == 1:
        return 2
# 738.单调递增的数字


# 版本1
class Solution:
    def monotoneIncreasingDigits(self, N: int) -> int:
        # 将整数转换为字符串
        strNum = str(N)
        # flag用来标记赋值9从哪里开始
        # 设置为字符串长度,为了防止第二个for循环在flag没有被赋值的情况下执行
        flag = len(strNum)

        # 从右往左遍历字符串
        for i in range(len(strNum) - 1, 0, -1):
            # 如果当前字符比前一个字符小,说明需要修改前一个字符
            if strNum[i - 1] > strNum[i]:
                flag = i  # 更新flag的值,记录需要修改的位置
                # 将前一个字符减1,以保证递增性质
                strNum = strNum[:i - 1] + str(int(strNum[i - 1]) - 1) + strNum[i:]

        # 将flag位置及之后的字符都修改为9,以保证最大的递增数字
        for i in range(flag, len(strNum)):#flag后面的都为9!
            strNum = strNum[:i] + '9' + strNum[i + 1:]

        # 将最终的字符串转换回整数并返回
        return int(strNum)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值