算法基础之二叉树相关实战(下)(Leetcode题型归纳)


3.路径和相关题目

3.1介绍

在这里插入图片描述

3.2真题分析

3.2.1路径总和(112)

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

#leetcode 112 方法1
class Solution:
    def hasPathSum(self, root: TreeNode, sum: int) -> bool:
        if root == None:
            return False

        # 当前节点是叶子,检查 root.val 值是否为 sum
        if root.left == None and root.right == None and root.val == sum:
            return True

        # 当前节点不是叶子,对它的所有孩子节点,递归调用 hasPathSum() 函数
        return self.hasPathSum(root.left,sum-root.val) or self.hasPathSum(root.right,sum-root.val)

在这里插入图片描述

#leetcode 112 方法2
class Solution:
    def hasPathSum(self, root: TreeNode, sum: int) -> bool:
        if root == None:
            return False

        stack = [(root,sum)]
        while stack:
            node,sum = stack.pop()
            # 判断叶子节点是否满足了条件
            if node.left == None and node.right == None and node.val == sum:
                return True
            
            # 左节点不为空,我们把左节点和剩余值打包压栈
            if node.left != None:
                stack.append((node.left,sum-node.val))
            # 右节点不为空,我们把右节点和剩余值打包压栈
            if node.right != None:
                stack.append((node.right,sum-node.val))

        return False

3.2.2路径总和2(113)

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

#leetcode113 方法1
class Solution:
    def pathSum(self, root: TreeNode, sum: int) -> List[List[int]]:
        # 辅助函数(因为需要一个变量记录路径)       
        def helper(root, sum, temp):
            if root == None:
                return

            # 路径和满足sum,路径添加到结果数组res
            if root.left == None and root.right == None and root.val == sum:
                temp += [root.val]
                res.append(temp)

            # 递归搜索左右子树,传入剩余和以及路径
            helper(root.left,sum-root.val,temp+[root.val])
            helper(root.right,sum-root.val,temp+[root.val])


        res = []
        helper(root,sum,[])

        return res
#leetcode113 方法2
class Solution:
    def pathSum(self, root: TreeNode, sum: int) -> List[List[int]]:
        if root == None:
            return []

        res = []
        temp = []
        stack = [(root,sum,temp)]

        while stack:
            node,sum,temp = stack.pop()
            # 判断叶子节点是否满足了条件
            if node.left == None and node.right == None and node.val == sum:
                temp += [node.val]
                res.append(temp)

            if node.left != None:
                stack.append((node.left,sum-node.val,temp + [node.val]))

            if node.right != None:
                stack.append((node.right,sum-node.val,temp + [node.val]))

        return res

3.2.3二叉树中的最大路径和(124)

在这里插入图片描述

在这里插入图片描述

3.2.4求根到叶子节点数字之和(129)

在这里插入图片描述
在这里插入图片描述

#leetcode129 递归
class Solution:
    def sumNumbers(self, root: TreeNode) -> int:
        def helper(root, nums):
            if root == None:
                return 0

            # 更新路径和
            nums *= 10
            nums += root.val

            # 如果已经是叶子节点,保存路径和到列表中
            if root.left == None and root.right == None:
                res.append(nums)

            if root.left != None:
                helper(root.left,nums)

            if root.right != None:
                helper(root.right,nums)

        
        res = []
        helper(root,0)

        return sum(res)
#leetcode129 迭代
class Solution:
    def sumNumbers(self, root: TreeNode) -> int:
        if root == None:
            return 0

        stack = [(root,0)]
        res = []

        while stack:
            node,nums = stack.pop()
            # 更新路径和
            nums *= 10
            nums += node.val

            # 如果已经是叶子节点,保存路径和到列表中
            if node.left == None and node.right == None:
                res.append(nums)

            if node.left != None:
                stack.append((node.left,nums))

            if node.right != None:
                stack.append((node.right,nums))

        return sum(res)

3.2.5 二叉树中的最大路径和(124)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#leetcode 124
class Solution:
    def __init__(self):
        self.maxSum = float("-inf")

    def maxPathSum(self, root: TreeNode) -> int:
        def maxGain(node):
            if not node:
                return 0

            # 递归计算左右子节点的最大贡献值
            # 只有在最大贡献值大于 0 时,才会选取对应子节点
            leftGain = max(maxGain(node.left), 0)
            rightGain = max(maxGain(node.right), 0)
            
            # 节点的最大路径和取决于该节点的值与该节点的左右子节点的最大贡献值
            priceNewpath = node.val + leftGain + rightGain
            
            # 更新答案
            self.maxSum = max(self.maxSum, priceNewpath)
        
            # 返回节点的最大贡献值
            return node.val + max(leftGain, rightGain)
   
        maxGain(root)
        return self.maxSum

3.2.6 二叉树的所有路径(257)

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

#leetcode257
class Solution:
    def binaryTreePaths(self, root: TreeNode) -> List[str]:
        if root == None:
            return None

        res = []
        queue = [(root,'')]

        while queue:
            temp = ''
            length = len(queue)

            for _ in range(length):
                node,temp = queue.pop(0)
                temp += str(node.val)

                # 如果是叶子节点,记录路径
                if node.left == None and node.right == None:    
                    res.append(temp)

                # 格式要求
                temp += '->'

                if node.left != None:
                    queue.append((node.left,temp))

                if node.right != None:
                    queue.append((node.right,temp))

        return res

4.二叉树的构建相关题目

4.1介绍

在这里插入图片描述

4.2真题分析

4.2.1从前序与中序遍历序列构造二叉树(105)

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

#leetcode 105
class Solution(object):
	def buildTree(self, preorder, inorder):
		if not (preorder and inorder):
			return None
		# 根据前序数组的第一个元素,就可以确定根节点	
		root = TreeNode(preorder[0])
		# 用preorder[0]去中序数组中查找对应的元素
		mid_idx = inorder.index(preorder[0])
		# 递归的处理前序数组的左边部分和中序数组的左边部分
		# 递归处理前序数组右边部分和中序数组右边部分
		root.left = self.buildTree(preorder[1:mid_idx+1],inorder[:mid_idx])
		root.right = self.buildTree(preorder[mid_idx+1:],inorder[mid_idx+1:])
		return root

4.2.2从中序与后续遍历序列构造二叉树(106)

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

#leetcode106
class Solution(object):
    def buildTree(self, inorder, postorder):
        if not (inorder and postorder):
            return None
        # 将中序数组的下标、值保存到map中省去解法一中线性查找
        d = {val:idx for idx,val in enumerate(inorder)}
        self.post_idx = len(postorder)-1
        def dfs(left,right):
            if left>right:
                return None
            # 从后序数组中拿最后一个元素,根据这个元素去map中找到中序数组对应的index
            # 然后递归的处理右边[index+1,right],递归处理左边[left,index-1]
            val = postorder[self.post_idx]
            self.post_idx -= 1
            root = TreeNode(val)
            index = d[val]
            root.right = dfs(index+1,right)
            root.left = dfs(left,index-1)
            return root
        return dfs(0,len(inorder)-1)

4.2.3根据前序和后续遍历构造二叉树(889)

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

#leetcode 889
class Solution(object):
    def constructFromPrePost(self, pre, post):
        def dfs(pre,post):
            if not pre:
                return None
            # 数组长度为1时,直接返回即可
            if len(pre)==1:
                return TreeNode(pre[0])
            # 根据前序数组的第一个元素,创建根节点     
            root = TreeNode(pre[0])
            # 根据前序数组第二个元素,确定后序数组左子树范围
            left_count = post.index(pre[1])+1
            # 递归执行前序数组左边、后序数组左边
            root.left = dfs(pre[1:left_count+1],post[:left_count])
            # 递归执行前序数组右边、后序数组右边
            root.right = dfs(pre[left_count+1:],post[left_count:-1])
            # 返回根节点
            return root
        return dfs(pre,post)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值