513. 找树左下角的值 - 力扣(LeetCode)
1. 第一想法
层序遍历, 最后一层的第一个元素就是我们要找的元素。
# 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 findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
node_queue = deque()
node_queue.append(root)
res_list = []
while node_queue:
size = len(node_queue)
for i in range(size):
node = node_queue.popleft()
if i == 0:
res_list.append(node.val)
if node.left:
node_queue.append(node.left)
if node.right:
node_queue.append(node.right)
return res_list[-1]
2. 看过文档后
代码随想录 (programmercarl.com)
思路差不多。
但是文档不使用res_list记录每一层的第一个,而是直接用一个变量,不断用list的第一个元素赋值。
3. 学习时长
10分钟。
112. 路径总和 - 力扣(LeetCode)
1. 第一想法
前序遍历。 但是前序遍历过程中,如果我们只使用一个变量统计一条路径的val的总和,那我们在当前叶子节点是其parent的右孩子时,如果我们要回退,我们会发现最多回退到它的parent,而因为parent早已经在之前给左右孩子压入栈时从栈中pop出来,所以这里根本没有办法再往回退。这就是我们实现迭代法前序遍历的唯一障碍。
2. 看完文档的收获。
代码随想录 (programmercarl.com) 此时,我们应该不仅仅只用stack记录node,还要记录从root到当前节点node的路径中val总和。
即stack.append((node, sum(root-->node)))。
所以具体实现如下:
# 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 hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
if root is None:
return False
else:
node_stack = list()
node_stack.append((root, root.val))
while node_stack:
node, node_sum = node_stack.pop()
if (not node.left) and (not node.right):
if node_sum == targetSum:
return True
if node.right:
node_stack.append((node.right, node_sum + node.right.val))
if node.left:
node_stack.append((node.left, node_sum + node.left.val))
return False
3. 学习时长
1小时。
113. 路径总和 II - 力扣(LeetCode)
1. 第一想法
同样是和上面一样的前序遍历,但是需要记录路径。 如果需要记录路径,我们就需要找到记录的时机。
只有当遇到叶子节点的时候,才能凑齐一条路径。 但是如果直到叶子节点才记录一条路径,实际上是没办法回溯的。 就像上一道题的困境一样,于是我的笨办法是,每个节点都要记录自己到root的路径列表,虽然存储占的大,但是能保证每一个叶子节点统计到真实的到root的路径。
2. 看过文档后的收获
至于113. 路径总和ii 的迭代法我并没有写,用迭代方式记录所有路径比较麻烦,也没有必要,如果大家感兴趣的话,可以再深入研究研究。
发现他并没有使用迭代法,而是直接递归,这个很方便,我也可以用递归来实现,就不知难而上了。
- 终止条件:如果节点是叶子,那就判断是否满足sumTarget,如果是则将当前路径加入到route_list,然后返回。
- 传入参数:当前root和一个临时路径,他从root出发,到叶子节点。以及从root到当前节点的value总和。
- 本层逻辑:
- 将value + root.val, list.append(root.val)
- 传给左侧子树递归,
- 传给右侧子树递归.
# 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 __init__(self):
self.route_list = []
def dfs(self, root, sum_val, targetSum, route: list):
if (not root.left) and (not root.right):
if sum_val + root.val == targetSum:
self.route_list.append(route + [root.val])
else:
if root.left:
self.dfs(root.left, sum_val + root.val, targetSum, route + [root.val])
if root.right:
self.dfs(root.right, sum_val + root.val, targetSum, route + [root.val])
def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
if root is None:
return []
else:
self.dfs(root, 0, targetSum, [])
return self.route_list
3. 学习时长
40分钟。
106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode)
1. 直接看文档
用后序遍历的后侧节点来分割中序遍历的序列,从而得到左右子树的后序遍历和中序遍历的序列。
所以我们使用分治递归去做。
# 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 buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
if postorder is None or len(postorder) == 0:
return None
root_val = postorder[-1]
root_inorder_idx = -1
for idx in range(len(inorder)):
if inorder[idx] == root_val:
root_inorder_idx = idx
break
left_child = self.buildTree(inorder[:root_inorder_idx], postorder[:root_inorder_idx])
right_child = self.buildTree(inorder[root_inorder_idx + 1 :], postorder[root_inorder_idx:-1])
return TreeNode(val=root_val, left=left_child, right=right_child)
3. 学习时长
30分钟
105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode)
1. 第一想法
和上述思路一样。
# 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 buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
if (preorder is None) or (len(preorder) == 0):
return None
else:
root_val = preorder[0]
mid_idx = -1
for idx in range(len(inorder)):
if inorder[idx] == root_val:
mid_idx = idx
break
left_child = self.buildTree(preorder[1:mid_idx + 1], inorder[:mid_idx])
right_child = self.buildTree(preorder[mid_idx + 1:], inorder[mid_idx + 1:])
return TreeNode(val=root_val, left=left_child, right=right_child)
2. 学习时长
5分钟。