代码随想录算法训练营第32天|56. 合并区间、738.单调递增的数字、968.监控二叉树

1.56. 合并区间

题目链接:56. 合并区间
文档讲解: 代码随想录

class Solution(object):
    def merge(self, intervals):
        """
        :type intervals: List[List[int]]
        :rtype: List[List[int]]
        """
        res = []
        #按照左边界排序
        intervals.sort(key = lambda x:x[0])
        #遍历
        for i in range(1, len(intervals)):
            if intervals[i][0] > intervals[i - 1][1]:
                #不重叠
                res.append(intervals[i - 1])
            else:
                #重叠
                intervals[i][0] = min(intervals[i - 1][0], intervals[i][0])
                intervals[i][1] = max(intervals[i - 1][1], intervals[i][1])
        #记录最后一个区间
        res.append(intervals[-1])
        return res
class Solution(object):
    def merge(self, intervals):
        """
        :type intervals: List[List[int]]
        :rtype: List[List[int]]
        """
        res = []
        #排序
        intervals.sort(key = lambda x:x[0])
        #记录第一个区间
        res.append(intervals[0])
        for i in range(1, len(intervals)):
            if intervals[i][0] <= res[-1][1]:
                #重叠,更新res区间右边界
                res[-1][1] = max(res[-1][1], intervals[i][1])
            else:
                #不重叠
                res.append(intervals[i])
        return res

2.738.单调递增的数字

题目链接:738.单调递增的数字
文档讲解: 代码随想录

class Solution(object):
    def monotoneIncreasingDigits(self, n):
        """
        :type n: int
        :rtype: int
        """
        #暴力解法
        for i in range(n, 0, -1):
            if self.check(i):
                return i 
        return 0

    def check(self, n):
        max_digit = 10
        while n > 0:
            digit = n % 10
            if max_digit >= digit:
                max_digit = digit
            else:
                return False
            n = n // 10
        return True
class Solution(object):
    def monotoneIncreasingDigits(self, n):
        """
        :type n: int
        :rtype: int
        """
        #将整数转换为字符串
        strNum = str(n)
        #flag标记从哪位开始赋值为9
        flag = len(strNum) #防止第二个for循环在flag没有被赋值的情况下执行

        for i in range(len(strNum) - 1, 0, -1):
            #如果当前字符比前一个字符小,则修改前一个字符
            if strNum[i] < strNum[i - 1]:
                #字符串不能修改
                strNum = strNum[:i - 1] + str(int(strNum[i - 1]) - 1) + strNum[i:]
                flag = i
        
        #for循环赋值9
        for i in range(flag, len(strNum)):
            strNum = strNum[:i] + '9' + strNum[i + 1:]

        return int(strNum)   

3.968.监控二叉树

题目链接:968.监控二叉树
文档讲解: 代码随想录

想要让摄像头数量最少,关键是摄像头放置的位置,需要从叶子节点后序遍历,因为叶子节点放不放摄像头省下的摄像头数量是指数阶别的,而头节点放不放摄像投就就省下一个。因此,局部最优是在叶子节点的父节点放置摄像头,所用摄像头数量最少。

接下来就是本题的难点:如何隔两个节点放置一个摄像头?
(1)此时需要状态转移,可以将节点的状态分为三种情况:无覆盖(0)、放置摄像头(1)、有覆盖(2)。
(2)递归函数的终止条件是,遇到空节点则return,那么空节点的状态应该是有覆盖。如果空节点标记为放置摄像头,那么叶子节点则是有覆盖的状态,这样的话其父节点不会放置摄像头。如果空节点标记为无覆盖,那么叶子节点需要放置摄像头。这两种情况都与期望不符。
(3)递归函数的单层逻辑:父节点接收左右孩子的状态信息。第一种情况,只要左右孩子有一个0,则父节点需要放置摄像头,为1状态。第二种情况,只要左右孩子有一个1,则父节点不用放置摄像头,为2状态。第三种情况,左右孩子都是2,则父节点是0状态。第四种情况,夫节点为头节点,且为状态0,则此时需要在头节点放置摄像头。

class Solution(object):
    def minCameraCover(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        self.res = 0
        tou = self.traversal(root)
        #如果头节点为0
        if tou == 0:
            self.res += 1
        return self.res
        

    def traversal(self, node):
        #终止条件
        if not node:
            return 2
        
        #后序遍历
        left = self.traversal(node.left)
        right = self.traversal(node.right)
        #处理中间节点
        #左右孩子至少一个0
        if left == 0 or right == 0:
            self.res += 1
            return 1
        #左右孩子至少一个1
        if left == 1 or right == 1:
            return 2
        #左右孩子都为2
        if left == 2 and right == 2:
            return 0

用elif精简:

class Solution(object):
    def minCameraCover(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        self.res = 0
        if self.traversal(root) == 0:
            self.res += 1
        return self.res
    
    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
        elif left == 0 or right == 0:
            #如果出现(1,0)的组合,优先判断是否有0
            self.res += 1
            return 1
        else:
            return 2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值