题目:树左下角的值
学习资料:代码随想录
实现过程
- 迭代法:层序遍历,遍历到最后一层返回最左侧的,i=0就是每一层最左边的结点。
- 递归法:需要记录深度最大的叶子结点,然后使用前序遍历,返回深度最大的结点,这样就是最左侧的
迭代法
#记录最后一行中最左侧的
queue = [root]
result = 0
while queue:
size = len(queue)
for i in range(size):
if i == 0:
result = queue[0].val
cur = queue.pop(0)
if cur.left:
queue.append(cur.left)
if cur.right:
queue.append(cur.right)
return result
递归法
maxLen_ = float("-inf")
result = 0
def tranversal(root, depth):
nonlocal maxLen_, result
if not root.left and not root.right:
if depth > maxLen_:
maxLen_ = depth
result = root.val
if root.left:
depth += 1
tranversal(root.left, depth)
depth -= 1
if root.right:
depth += 1
tranversal(root.right, depth)
depth -= 1
return
tranversal(root, 0)
return result
Leetcode 112
题目:路径总和
学习资料:代码随想录
实现过程
- 递归方法:
- 参数需要root和计数器counter;可以采用递减的方式,当碰到叶子结点同时counter为0时就返回True
- 终止条件就是,当碰到叶子结点同时counter为0时就返回True;如果碰到叶子结点路径不满足,返回False
- 单层逻辑:不考虑空结点,要进行回溯;如果直接在参数位置进行counter计算则是隐藏回溯
- 注意初始放入的逻辑是counter减去root的val,这里counter记录的是剩余的总和
def tranversal(root, counter):
if (not root.left) and (not root.right) and counter == 0:
return True
if not root.left and not root.right:
return False
if root.left:
counter -= root.left.val
if tranversal(root.left, counter):
return True
counter += root.left.val
if root.right:
counter -= root.right.val
if tranversal(root.right, counter):
return True
counter += root.right.val
return False
if root == None:
return False
else:
return tranversal(root, targetSum-root.val)
Leetcode 113
题目:路径总和
学习资料: 代码随想录
实现过程
- 递归三部曲:
- 传入参数:结点和计数器count,注意计数器使用减法的方式
- 终止条件:同上;两个终止条件:当count为0且为叶子结点证明路径找到,添加到结果中;如果为叶子结点但不为0,则没有找到
- 单层循环:利用到回溯的思想;需要path来存储路径,result存储结果;要pop出之前添加的结点
def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
result = []
path = []
def trace(cur, count):
if not cur.left and not cur.right and count == 0:
result.append(path[:])
return
if not cur.left and not cur.right:
return
if cur.left:
path.append(cur.left.val)
trace(cur.left, count - cur.left.val)
path.pop()
if cur.right:
path.append(cur.right.val)
trace(cur.right, count - cur.right.val)
path.pop()
# return
# 判读空的情况
if not root:return result
path.append(root.val)
trace(root, targetSum - root.val)
return result
Leetcode 106
题目:中序后序构造二叉树
学习资料: 代码随想录
实现过程
- 后序数组长度为0,则为空节点
- 从后序数组中最后一个数字得到root节点
- 根据root节点,在中序数组中找到对应的index
- 根据index划分中序数组,左区间和右区间
- 根据中序数组的左右区间划分后序数组
- 递归上述过程,最终返回root
- 如果后序长度为1说明,为叶子节点或者只有一个root,直接返回root
def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
def trace(inorder, postorder):
if len(postorder) == 0:
return
rootvalue = postorder[-1]
root = TreeNode(rootvalue)
if len(postorder) == 1:
return root
#找到root在inorder中的位置
ind = inorder.index(rootvalue)
left_in, right_in = inorder[:ind], inorder[ind+1:]
#利用中序中分割出来的左右区间在后序中去分割
left_out, right_out = postorder[:len(left_in)], postorder[len(left_in):len(left_in)+len(right_in)]
#返回左右结点
root.left = trace(left_in, left_out)
root.right = trace(right_in, right_out)
return root
return trace(inorder, postorder)
总结
- 递归时返回什么?
- 如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值
- 如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返回值。
- 如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回。
- 一般需要搜索整棵树的时候,会用到递归的思想
- 构造二叉树必须有中序遍历的结果