找树左下角的值+路径总和+从前序和中序遍历序列构造二叉树(day18*)
这篇可以主要关注一下如何确定递归时是否需要返回值。
LC513. 找树左下角的值
给定一个二叉树的根节点,请找出该二叉树的 最底层最左边 节点的值。
思路1 层序遍历
class Solution:def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:if not root: return -1# leverOrderfrom collections import dequeque = deque()que.append(root)while que:size = len(que)for i in range(size):node = que.popleft()if i == 0:ans = node.valif node.left: que.append(node.left)if node.right: que.append(node.right)return ans思路2 深度优先方法要困难一些,递归判断结点是否是深度最大的叶子结点,只遍历,没有进行什么操作,所以不需要有返回值。这种写法是隐含了回溯的,不需要自己写,因为函数调用完形参就释放了。
class Solution:def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:def isleaf(root):return root and not root.left and not root.right# 深度优先 max_depth = 0target = root.valdef dfs(root, depth):nonlocal max_depth, targetif not root: return depth += 1if isleaf(root):if depth > max_depth:max_depth = depthtarget = root.valdfs(root.left, depth)dfs(root.right, depth)dfs(root, 0)return target下面这种写法是把回溯写出来了,因为depth一直在变的。
class Solution:def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:def isleaf(root):return root and not root.left and not root.rightleftval = root.valmax_d = 0depth = 0def dfs(root):nonlocal leftval, max_d, depthif not root: returndepth += 1if isleaf(root):if depth > max_d:max_d = depthleftval = root.valif root.left:dfs(root.left)depth -= 1if root.right:dfs(root.right)depth -= 1dfs(root)return leftvalLC112. 路径总和
给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false。
下面是我自己的写法,虽然AC了(其中要注意ans写成nonlocal),但是问题是找到了目标路径和之后还是会进行一整个树的遍历。
class Solution:def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:def isleaf(root):return root and not root.left and not root.right# 先序遍历ans = Falsepathsum = 0def dfs(root, pathsum):nonlocal ansif not root: return pathsum += root.valif isleaf(root):if pathsum == targetSum:ans = Trueif root.left: dfs(root.left, pathsum)if root.right: dfs(root.right, pathsum)dfs(root,pathsum)return ans本题搜索出一条符合条件的路径即可,所以递归一定要有返回值,遇到符合的路径要及时返回。下面的写法好多了。
class Solution:def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:def isleaf(root):return root and not root.left and not root.right# 先序遍历def dfs(root, pathsum) -> bool:pathsum += root.val# 叶子结点如果找到了路径和,True;否则Falseif isleaf(root):if pathsum == targetSum:return Trueelse:return False# 如果左孩子里面找到了路径和,返回Trueif root.left: if dfs(root.left, pathsum):return True# 如果右孩子里面找到了路径和,返回Trueif root.right: if dfs(root.right, pathsum):return True# 都没有找到,返回Falsereturn Falseif not root: return False #这一行也重要return dfs(root,0)LC113. 路径总和 II
给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有从根节点到叶子节点路径总和等于给定目标和的路径。
本题是需要遍历完整棵树,且不用处理递归返回值,就不需要返回值。
class Solution:def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:def isleaf(root):return root and not root.left and not root.rightpaths = []path = []def dfs(root, sum_pre):if not root: returnpath.append(root.val)sum_pre += root.val# print(sum_pre, path)if isleaf(root) and sum_pre == targetSum: #写的时候isleaf后面的(root)也忘了写,就变成了是否存在isleaf函数,就一直都是True。多花了时间调试,写的时候就要慢慢细致地写。paths.append(path[:]) #[:]不要忘了加if root.left:dfs(root.left, sum_pre)path.pop()if root.right:dfs(root.right, sum_pre)path.pop()dfs(root, 0)return pathsLC106. 从中序与后序遍历序列构造二叉树
这题没有看答案一次AC了,大晚上的开心了好一会儿~这草稿也是只有自己能看懂了LOL。
本题需要遍历完整棵树,但需要对递归返回值(结点)进行处理(链接),所以需要有返回值。
# Definition for a binary tree node. # class TreeNode: # def __init__(self, val=0, left=None, right=None): # self.val = val # self.left = left # self.right = right class Solution:def find(self, nums, val):for i, num in enumerate(nums):if num == val:return ireturn -1def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:# def constructTree(inorder, postorder: List[int]) -> Optional[TreeNode]:if not inorder: return Noneif len(inorder) == 1: return TreeNode(inorder[0])m = postorder[-1]node = TreeNode(m)i = self.find(inorder, m)print(m,i)l_inorder = inorder[0:i]r_inorder = inorder[i+1:]l_postorder = postorder[0:i]r_postorder = postorder[i:-1]node.left = self.buildTree(l_inorder,l_postorder)node.right = self.buildTree(r_inorder,r_postorder)return nodeLC105. 从前序与中序遍历序列构造二叉树
给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。
和上题一样的写法,但写find函数时出现了小问题,要在循环结束时还没return才返回-1。
class Solution:def find(self, nums, val):for i, num in enumerate(nums):if num == val:return ireturn -1def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:if not preorder: return NoneNode = TreeNode(preorder[0])mid = preorder[0]i = self.find(inorder, mid)l_inorder, r_inorder = inorder[0:i], inorder[i+1:]l_preorder, r_preorder = preorder[1:i+1], preorder[i+1:]Node.left = self.buildTree(l_preorder, l_inorder)Node.right = self.buildTree(r_preorder, r_inorder)return Node看了答案之后发现在list中查找元素的时候,不需要自己写函数,用自身的index方法,直接i = inorder.index(mid)即可。
明天加油~
参考资料:路径总和-代码随想录
总结
以上是生活随笔为你收集整理的找树左下角的值+路径总和+从前序和中序遍历序列构造二叉树(day18*)的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 清华女硕士代言西湖名胜六和塔(组图),张
- 下一篇: 【滴滴出行】2017秋招笔试真题(智力题