leetcode笔记|第五周 树专题

二叉树相关基础知识
https://blog.csdn.net/xiaoquantouer/article/details/65631708
leetcode二叉树相关教程
https://leetcode-cn.com/leetbook/read/illustration-of-algorithm/59slxe/
https://leetcode-cn.com/leetbook/detail/data-structure-binary-tree/

剑指offer 27 二叉树的镜像

python可以平行赋值,就很方便。当tree为空的时候,return /。return。None / return root 都可以。时间复杂度:需要遍历所有节点O(N),空间复杂度:二叉树O(log(n),退化成链表O(n)。

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def mirrorTree(self, root):
        """
        :type root: TreeNode
        :rtype: TreeNode
        """
        if not root: return  # 为空的情况 return None return root 都对
        root.right, root.left = self.mirrorTree(root.left), self.mirrorTree(root.right)
        return root

108 将升序数组转换为高度平衡二叉搜索树

BST的中序遍历为递增序列,所以可以最简单的,这个升序数组的中间为root,小的在左分支,大的在右分支。返回node,得到的就是整个BST。

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def sortedArrayToBST(self, nums):
        """
        :type nums: List[int]
        :rtype: TreeNode
        """
        if not len(nums): return # 考虑为空
        mid = (len(nums)) // 2
        node = TreeNode(nums[mid])
        left = nums[:mid]
        right = nums[mid+1:]
        node.left, node.right = self.sortedArrayToBST(left), self.sortedArrayToBST(right)
        return node

979 在二叉树中分配硬币

深度优先搜索,每一个node的当前金币数与1的差距就是过载量,也就是要走或者来的数量。叶子结点的和为返回的次数,每个叶子结点的过载量计算公式为 .val+L+R-1。

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def distributeCoins(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        self.ans = 0
        def dfs(node):
            if not node: return 0 # not node时 没有.left .right 没有这句话下面会报错
            L, R = dfs(node.left), dfs(node.right)
            self.ans += abs(L) + abs(R)
            return node.val + L + R - 1
        dfs(root)
        return self.ans

1457 二叉树中的伪回文路径

二叉树的每一条路径,如果是可以组成回文串,就称为伪回文路径。计算root的伪回文路径数目。想法就是拿出每条路径(直到叶子结点),判断是否回文。拿出路径,使用list实现,每个不是叶子结点的node.val加入到path这个list中;判断是否叶子结点就是判断是否左右子结点都为None。判断是否回文,由于乱序,因此判断是否奇数个的字母只有一个即可。奇数可用&1 位计算实现。

from collections import Counter

class Solution(object):
    def pseudoPalindromicPaths (self, root):
        def huiwen(path):
            coun = Counter(path)
            odd_num = 0
            for i in coun:
                if coun[i] & 1:
                    odd_num += 1
                if odd_num == 2:
                    return False
            return True

        if not root: return
        
        self.ans = 0
        stack = [([root.val],root)]
        while stack:
            path, node = stack.pop()
            if not node.left and not node.right:
                if huiwen(path):
                    self.ans += 1
            if node.left:
                stack.append((path+[node.left.val], node.left))
            if node.right:
                stack.append((path+[node.right.val], node.right))

        return self.ans

1130 叶值的最小代价生成树

正整数数组,相邻两个叶子结点的父节点是两者的乘积,叶子结点顺序就按照数组的顺序排列,最终希望得到的非子节点的和越来越小。如此,比如四个,1234,可以12的到父节点,34得到父节点,然后两个父节点乘积得到根,求三个生成的非子节点的和最小。如果要求最小,其实有trick,就是让最小值在最底层,多次相乘求和这样比大的在最底层多次相乘求和要小得多。所以1,2,34,先34相乘求父节点,与2相乘求父节点,在于1相乘,1是最大的人,乘最多次的3/4最小,那么多个父节点的和是最小的。因此,可以循环遍历两个相邻的乘积最小的,丢掉较小的那一个,留下较大的那一个后面计算父节点要用,因为是每支树max的元素的乘积。ps,计算完相乘结果后加入入res中,求和。

class Solution:
    def mctFromLeafValues(self, arr: List[int]) -> int:
        res = 0
        while len(arr)>=2:
            n = len(arr)
            select= 0
            min_mul = arr[0] * arr[1]
            for i in range(1, n-1):
                if arr[i] * arr[i+1] < min_mul:
                    min_mul = arr[i] * arr[i+1]
                    select = i
            if arr[select] < arr[select+1]: 
                del arr[select]
            else:
                del arr[select+1]
            res += min_mul
        return res

124 二叉树中的最大路径和

就是找一个二叉树的路径,和最大。路径6和就是当前节点+左子树+右子树,如果两个子树小于0那就不要了。

class Solution:
    def maxPathSum(self, root: TreeNode) -> int:
        self.ans = float('-inf')

        def dfs(root):
            if not root: return 0
            right = dfs(root.right)
            left = dfs(root.left)
            self.ans = max(self.ans, left+right+root.val)
            return max(0, max(left, right)+root.val)

        dfs(root)
        return self.ans

968 监控二叉树

套路:遍历树,从下往上,当子节点xxx的时候,父节点应该是xxx的,同时设置一个变量self.res循环地更新。最终的节点状态是xxx的时候,会怎么影响self.res。这里每个节点可能:子节点需要相机,这个节点放一个相机;子节点放了相机,这个节点不需要相机;子节点被相机拍了,这个节点需要相机。注意临界条件,叶子结点的左右子节点可以看作被拍了;根节点需要相机的时候,最终数目+1。

class Solution(object):
    def minCameraCover(self, root):
        self.res = 0
        def judge(node):
            if not node: return 0 # 无子节点可认为子节点被拍了
            left = judge(node.left)
            right = judge(node.right)
            if not left and not right:
                return 1 # need camera
            if left == 1 or right == 1:
                self.res += 1
                return 2 # put a camera
            if left == 2 or right == 2:
                return 0 # dont need a camera
        if judge(root) == 1: # 最终need camera要加一个哦
            self.res += 1
        return self.res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值