513.找树左下角的值
知识点一:global和nonlocal
当内部作用域想修改外部作用域的变量时,就要用到 global 和 nonlocal 关键字了。以下实例修改全局变量 num:
num = 1
def fun1():
global num
print(num)
num = 123
print(num)
fun1()
print(num)
以上实例输出结果:
1
123
123
如果要修改嵌套作用域(enclosing 作用域,外层非全局作用域)中的变量则需要 nonlocal 关键字了,如下实例:
def outer():
num = 10
def inner():
nonlocal num # nonlocal关键字声明
num = 100
print(num)
inner()
print(num)
outer()
以上实例输出结果:
100
100
class Solution:
def findBottomLeftValue(self, root: Optional[TreeNode]) -> int:
max_depth = -float("INF")
leftmost_val = 0
def __traverse(root, cur_depth):
nonlocal max_depth, leftmost_val
if not root.left and not root.right:
if cur_depth > max_depth:
max_depth = cur_depth
leftmost_val = root.val
if root.left:
cur_depth += 1
__traverse(root.left, cur_depth)
cur_depth -= 1
if root.right:
cur_depth += 1
__traverse(root.right, cur_depth)
cur_depth -= 1
__traverse(root, 0)
return leftmost_val
112. 路径总和
class solution:
def haspathsum(self, root: treenode, targetsum: int) -> bool:
def isornot(root, targetsum) -> bool:
if (not root.left) and (not root.right) and targetsum == 0:
return true # 遇到叶子节点,并且计数为0
if (not root.left) and (not root.right):
return false # 遇到叶子节点,计数不为0
if root.left:
targetsum -= root.left.val # 左节点
if isornot(root.left, targetsum): return true # 递归,处理左节点
targetsum += root.left.val # 回溯
if root.right:
targetsum -= root.right.val # 右节点
if isornot(root.right, targetsum): return true # 递归,处理右节点
targetsum += root.right.val # 回溯
return false
if root == none:
return false # 别忘记处理空treenode
else:
return isornot(root, targetsum - root.val)
113.路径总和ii
class Solution:
def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
def dfs(root,targetSum,path):
if root:
path.append(root.val)
if (not root.left) and (not root.right) and root.val == targetSum:
res.append(path[:])
dfs(root.left,targetSum-root.val,path)
dfs(root.right,targetSum-root.val,path)
path.pop()
res = []
dfs(root,targetSum,[])
return res
106.从中序与后序遍历序列构造二叉树
一共分几步:
-
第一步:如果数组大小为零的话,说明是空节点了。
-
第二步:如果不为空,那么取后序数组最后一个元素作为节点元素。
-
第三步:找到后序数组最后一个元素在中序数组的位置,作为切割点
-
第四步:切割中序数组,切成中序左数组和中序右数组 (顺序别搞反了,一定是先切中序数组)
-
第五步:切割后序数组,切成后序左数组和后序右数组
-
第六步:递归处理左区间和右区间
class Solution:
def buildTree(self, inorder: List[int], postorder: List[int]) -> Optional[TreeNode]:
# 第一步: 特殊情况讨论: 树为空. 或者说是递归终止条件
if not postorder:
return
# 第二步: 后序遍历的最后一个就是当前的中间节点
root_val = postorder[-1]
root = TreeNode(root_val)
# 第三步: 找切割点.
root_index = inorder.index(root_val)
# 第四步: 切割inorder数组. 得到inorder数组的左,右半边.
left_inorder = inorder[:root_index]
right_inorder = inorder[root_index + 1:]
# 第五步: 切割postorder数组. 得到postorder数组的左,右半边.
# ⭐️ 重点1: 中序数组大小一定跟后序数组大小是相同的.
left_postorder = postorder[:len(left_inorder)]
right_postorder = postorder[len(left_inorder): len(postorder) - 1]
# 第六步: 递归
root.left = self.buildTree(left_inorder, left_postorder)
root.right = self.buildTree(right_inorder, right_postorder)
# 第七步: 返回答案
return root
105.从前序与中序遍历序列构造二叉树
# 第一步: 特殊情况讨论: 树为空. 或者说是递归终止条件
if not preorder:
return None
# 第二步: 前序遍历的第一个就是当前的中间节点.
root_val = preorder[0]
root = TreeNode(root_val)
# 第三步: 找切割点.
separator_idx = inorder.index(root_val)
# 第四步: 切割inorder数组. 得到inorder数组的左,右半边.
inorder_left = inorder[:separator_idx]
inorder_right = inorder[separator_idx + 1:]
# 第五步: 切割preorder数组. 得到preorder数组的左,右半边.
# ⭐️ 重点1: 中序数组大小一定跟前序数组大小是相同的.
preorder_left = preorder[1:1 + len(inorder_left)]
preorder_right = preorder[1 + len(inorder_left):]
# 第六步: 递归
root.left = self.buildTree(preorder_left, inorder_left)
root.right = self.buildTree(preorder_right, inorder_right)
return root
- 自己看到题目的第一想法
毫无头绪
- 看完代码随想录之后的想法
- 自己实现过程中遇到哪些困难
- 今日收获,记录一下自己的学习时长