LeetCode算法刷题(python) Day39|08贪心算法|738.单调递增的数字、968.监控二叉树

LeetCode 738.单调递增的数字

力扣题目链接
本题的核心是若当前数字不是递增的,找到需要减1 的位置,后面全部改为9,比如332改为29912200改为11999

  • 从后向前遍历每个数字,如果nums[i-1] > nums[i],则nums[i-1] -= 1,并且记录当前的索引idx = i-1
  • 再向前比较,如果还需要修改,更新当前的索引idx。目的是为了找到需要减1的位置。因为仔细想一下,只需要某一个位置-1,后面全变成9即可,这样才能保证数字尽可能大
class Solution:
    def monotoneIncreasingDigits(self, n: int) -> int:
        # string = str(n)
        nums = [int(x) for x in str(n)]
        result = nums[:]
        length = len(nums)
        if length == 1:
            return n
        # 寻找需要 减1 的位置
        idx = -1
        for i in range(length - 1, 0, -1):
            if nums[i - 1] > nums[i]:
                nums[i - 1] -= 1
                idx = i - 1
        
        if idx == -1: # 原本就是递增的
            return n
        else:
            # 需要减1 的位置后面全部改为9
            result[idx] -= 1
            for i in range(idx+1, length):
                result[i] = 9
        result = int(''.join(map(str, result)))
        return result

LeetCode 968.监控二叉树

力扣题目链接

思路:摄像头可以覆盖上中下三层,如果将摄像头放在叶子节点上就浪费了一层覆盖范围,所有优先放在叶子节点的父节点上,然后隔两个节点放一个摄像头。

首先我们为每个节点定义三种状态:

  • 0: 无覆盖
  • 1: 有摄像头
  • 2: 有覆盖

由于我们从叶子节点开始考虑如何放摄像头,应该用后序遍历(左右中),由左右孩子的状态推导中间节点的状态

  • 情况一:左右节点都有覆盖,此时该节点应无覆盖(等着该节点的父节点添加摄像头来覆盖)
  • 情况二:左右节点至少有一个无覆盖的情况,此时该节点需添加摄像头,全局变量摄像头数量+=1
  • 情况三:左右节点至少有一个有摄像头,此时该节点是有覆盖状态(情况二优先于情况三)

此外还需考虑空节点的状态,空节点是叶子节点的子节点,为了在叶子节点的父节点上放摄像头,叶子节点应是无覆盖状态,则空节点应是有覆盖状态,才能满足情况一使得叶子节点无覆盖。

这三种情况囊括了所有情况,递归返回的值为根结点的状态,如果此时根结点未被覆盖(情况一的特殊情况,即根结点没有父节点),需要在根结点加一个摄像头
在这里插入图片描述

class Solution:
    def __init__(self):
        self.result = 0
    def minCameraCover(self, root: Optional[TreeNode]) -> int:
        if self.traversal(root) == 0: # 根结点未被覆盖
            self.result += 1
        return self.result
    
    def traversal(self, node):
        if not node: return 2
        left = self.traversal(node.left)
        right = self.traversal(node.right)
        
        # 情况一
        if left == 2 and right == 2:
            return 0
        # 情况二
        if left == 0 or right == 0:
            self.result += 1
            return 1
        # 情况三
        if left == 1 or right == 1:
            return 2

今日毕!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值