以上题目可共用一个模板(dfs记录数的col和row),不同之处就是使用哈希表的时候调整一下key和value,n叉树的情况只需要用一个for循环来遍历每一个child来代替二叉树中的左右子树:
# 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 verticalTraversal(self, root: Optional[TreeNode]) -> List[List[int]]:
dic=defaultdict(list)
def dfs(node,row,col):
if node is None:
return
dic[col].append((row,node.val))
dfs(node.left,row+1,col-1)
dfs(node.right,row+1,col+1)
dfs(root,0,0)
ans=[]
for _,i in sorted(dic.items()):
i.sort()
ans.append([j for _,j in i])
return ans
更新103题的写法,在模板基础上加入一个flag来判断深度是否是偶数:
# 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 zigzagLevelOrder(self, root: Optional[TreeNode]) -> List[List[int]]:
dic=defaultdict(list)
def dfs(node,row,col):
if node is None:
return
dic[row].append((col,node.val))
dfs(node.left,row+1,col-1)
dfs(node.right,row+1,col+1)
dfs(root,0,0)
ans=[]
flag=0
for _, j in sorted(dic.items()):
res=[]
if flag%2==0:
for i in range(len(j)):
res.append(j[i][1])
else:
for i in range(len(j)-1,-1,-1):
res.append(j[i][1])
flag+=1
ans.append(res)
return ans
二叉树的前中后序遍历虽然是很基础的算法,但是我看到了一个很有意思的解题思路,特此记录一下:
# 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 inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
"""
#方法一
white,gray=0,1
ans=[]
stack=[(white,root)]
while stack:
color,node=stack.pop()
if node is None:
continue
if color==white:
stack.append((white,node.right))
stack.append((gray,node))
stack.append((white,node.left))
else:
ans.append(node.val)
return ans
"""
#方法二
ans=[]
def mid(node):
if node is not None:
mid(node.left)
ans.append(node.val)
mid(node.right)
mid(root)
return ans
解题思路,先判断两个节点是否处于同一深度,如果不是同一深度,则让更深的节点向上移动至同一深度,随后两节点一同向上移动,直到两节点的父节点是同一节点时停止,这样就找到了最近公共祖先:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def find_depth(self, root, node):
if not root:
return 0
if root == node:
return 1
left_depth = self.find_depth(root.left, node)
right_depth = self.find_depth(root.right, node)
if left_depth > 0:
return left_depth + 1
elif right_depth > 0:
return right_depth + 1
else:
return 0
def find_parent(self, root, node):
if not root or not node:
return None
if root.left == node or root.right == node:
return root
parent = self.find_parent(root.left, node)
if not parent:
parent = self.find_parent(root.right, node)
return parent
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
depth_p, depth_q = self.find_depth(root, p), self.find_depth(root, q)
while depth_p > depth_q:
p = self.find_parent(root, p)
depth_p -= 1
while depth_q > depth_p:
q = self.find_parent(root, q)
depth_q -= 1
while q != p:
p = self.find_parent(root, p)
q = self.find_parent(root, q)
return p
106和105可以构建出唯一一棵二叉树,而889能构建不止一棵。使用递归的时候注意细节,由于前序遍历的顺序是中左右,所以105题先递归左子树后右子树。而后序遍历顺序是左右中,106题需要先递归右子树,后左子树。因为确定根节点位置是根据前序遍历和后序遍历来确定的(分别使用了pop(0)和pop():
# 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 not preorder or not inorder:
return None
root_val = preorder.pop(0)
root = TreeNode(root_val)
root_position = inorder.index(root_val)
root.left = self.buildTree(preorder, inorder[:root_position])
root.right = self.buildTree(preorder, inorder[root_position + 1:])
return root