本文目录
513.找树左下角的值
代码随想录:513.找树左下角的值
Leetcode:513.找树左下角的值
做题
层序遍历。
class Solution:
def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
if not root:
return None
queue = collections.deque()
queue.append(root)
while queue:
for i in range(len(queue)):
if i == 0:
cur = queue[0].val
node = queue.popleft()
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
return cur
看文章
层序遍历很简单,主要看递归,递归就是记录一下当前深度,然后在深度变大时更新一下result。
class Solution:
def findBottomLeftValue(self, root: TreeNode) -> int:
self.max_depth = float('-inf')
self.result = None
self.traversal(root, 0)
return self.result
def traversal(self, node, depth):
if not node.left and not node.right:
if depth > self.max_depth:
self.max_depth = depth
self.result = node.val
return
if node.left:
depth += 1
self.traversal(node.left, depth)
depth -= 1
if node.right:
depth += 1
self.traversal(node.right, depth)
depth -= 1
112. 路径总和
代码随想录:112. 路径总和
Leetcode:112. 路径总和
做题
瞅了一眼之前做的记录,发现很简单,也很快get到思路…
class Solution:
def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
if root is None:
return False
if not root.left and not root.right and root.val == targetSum:
return True
return self.hasPathSum(root.left, targetSum - root.val) or self.hasPathSum(root.right, targetSum - root.val)
看文章
递归比较简单,迭代比较麻烦。
113.路径总和ii
做题
按照直接找路径的思路写了一下,思路差不多,但细节有bug。主要有2个点:
- 我传入的是path这个参数,所以在保存到res的时候,要先copy一下再存入(或者用list(path)也行,总之就是要另存或转换为一个新对象再存入),否则res里的结果会根据path的变化而变化。
- 必须找到叶子结点才能终止。
- targetSum可能是负数,故不需要判断节点值是否小于targetSum,只需要都搜索到叶子结点即可。
最后AC的代码如下:
class Solution:
def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
if not root:
return []
res = []
path = []
self.findPath(root, targetSum, res, path)
return res
def findPath(self, node, target, res, path):
if node.val == target and not node.left and not node.right:
path.append(node.val)
res.append(path.copy())
path.pop()
else:
path.append(node.val)
if node.left:
self.findPath(node.left, target - node.val, res, path)
if node.right:
self.findPath(node.right, target - node.val, res, path)
path.pop()
看文章
同样是迭代比较麻烦,就先不看了。
106.从中序与后序遍历序列构造二叉树
重点题目!!!笔试没做出来的题!!!
代码随想录:106.从中序与后序遍历序列构造二叉树
Leetcode:106.从中序与后序遍历序列构造二叉树
做题
直接看文章。
看文章
已知:中序、后序。
具体步骤如下:
- 后序数组是左右中,root节点一定是最后一个值。
- 根据root节点回到中序数组,root左边的节点一定是root的左子树,右边的节点一定是root的右子树。
- 根据左子树和右子树回到后序数组,切分出左右子树。此时回到1,分别从左右子树递归寻找。
class Solution:
def buildTree(self, inorder: List[int], postorder: List[int]) -> TreeNode:
# 第一步: 特殊情况讨论: 树为空. (递归终止条件)
if not postorder:
return None
# 第二步: 后序遍历的最后一个就是当前的中间节点.
root_val = postorder[-1]
root = TreeNode(root_val)
# 第三步: 找切割点.
separator_idx = inorder.index(root_val)
# 第四步: 切割inorder数组. 得到inorder数组的左,右半边.
inorder_left = inorder[:separator_idx]
inorder_right = inorder[separator_idx + 1:]
# 第五步: 切割postorder数组. 得到postorder数组的左,右半边.
# ⭐️ 重点1: 中序数组大小一定跟后序数组大小是相同的.
postorder_left = postorder[:len(inorder_left)]
postorder_right = postorder[len(inorder_left): len(postorder) - 1]
# 第六步: 递归
root.left = self.buildTree(inorder_left, postorder_left)
root.right = self.buildTree(inorder_right, postorder_right)
# 第七步: 返回答案
return root
105.从前序与中序遍历序列构造二叉树
做题
理解思路后,只需要调整下逻辑。代码如下:
class Solution:
def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
if not preorder:
return None
root_val = preorder[0]
root = TreeNode(root_val)
separator_index = inorder.index(root_val)
inorder_left = inorder[:separator_index]
inorder_right = inorder[separator_index + 1:]
preorder_left = preorder[1: len(inorder_left)+1]
preorder_right = preorder[len(inorder_left)+1:]
root.left = self.buildTree(preorder_left, inorder_left)
root.right = self.buildTree(preorder_right, inorder_right)
return root
看文章
思路一致。
以往忽略的知识点小结
- 可以在递归时记录深度,以找到最底层的节点
- 使用中序+后序、前序+中序构造唯一二叉树。具体操作为:
- 使用前序/后序的特点,找到唯一的“中”,回到中序数组进行分割,分割出左右子树的中序数组;
- 根据分割的左右子树长度,回到前序/后序数组,分割出左右子树的前序/后序数组;
- 分别通过左子树的中序+前序/后序数组、右子树的中序+前序/后序数组,递归构建二叉树即可。
- 如果有二叉树有重复值,上面的问题还能求解吗?不能。
- 前序+后序无法构造唯一二叉树。
个人体会
完成时间:1h50min。
心得:注意在递归时可以记录深度;使用中序+后序、前序+中序构造唯一二叉树,总体思路是递归,首先是在前序/后序数组找到“中”,回到中序做分割,然后再根据分割的长度,再分割前序/后序数组,得到左右子树各自的中序+前序/后序数组,最后递归即可。使用中序+后序、前序+中序构造唯一二叉树是重点,之前笔试折戟过,必须掌握!!!