赞
踩
层次遍历在树的遍历中有着非常重要的地位,本篇博客提出两种遍历方式,一种是最基本的使用队列完成的非递归遍历,一种是遍历过程中统计遍历层数的递归遍历,这种统计层数的好处是可以记录下每层的节点信息,对于找特殊层的元素或者对层次进行特殊操作极为方便。
def levelorder(root):
res,queue=[],[root]
if not root:
return res
while queue:
node=queue.pop(0)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
res.append(node)
return res
因为是多叉树,使用二叉树递归左右子树的遍历方式不太合适,所以使用非递归的迭代方式进行遍历。
def levelOrder(self, root: 'Node') :
if not root:
return []
res = []
cur = [root]
while cur:
next = []
temp = []
for node in cur:
temp.append(node.val)
next += node.children
res.append(temp)
cur = next
return res
这个题的难点在于有值的两个节点之间空的节点也会被统计进去,所以需要在层次遍历的时候记录下左右节点的index,然后使用动态规划的方法得到最大的宽度值。
def widthOfBinaryTree(self, root: TreeNode) : if not root: return 0 queue=[] res=0 queue.append([root,1]) while queue: n=len(queue) left=queue[0][1] right=0 for i in range(n): x=queue.pop(0) right=x[1] if x[0].left: queue.append([x[0].left,right*2]) if x[0].right: queue.append([x[0].right,right*2+1]) res=max(res,right-left+1) return res
def levelOrderBottom(self, root: TreeNode) :
res=[]
def helper(root, depth):
if not root:
return
if len(res)==depth:
res.append([])
res[depth].append(root.val)
helper(root.left,depth+1)
helper(root.right,depth+1)
helper(root,0)
return res
按照3的代码模板,只需要加上对depth的奇偶判断,然后调整插入元素的方向即可。
def zigzagLevelOrder(self, root: TreeNode) :
res=[]
def helper(root,depth):
if not root:
return
if len(res)==depth:
res.append([])
if depth%2==0:
res[depth].append(root.val)
else:
res[depth].insert(0,root.val)
helper(root.left,depth+1)
helper(root.right,depth+1)
helper(root,0)
return res
使用3的模板记录下每层的节点信息,保存成list(res),然后遍历res,取出res中的每个元素(list格式)的最后一个元素即可。(如果是左视图,就取出res中的每个元素的第一个元素即可)
def rightSideView(self, root: TreeNode) :
res=[]
def helper(root,depth):
if not root:
return res
if len(res)==depth:
res.append([])
res[depth].append(root.val)
helper(root.left,depth+1)
helper(root.right,depth+1)
helper(root,0)
num=[]
for res_each in res:
num.append(res_each[-1])
return num
当然,这个题也可以直接使用非递归层次遍历去做,代码如下:
def rightSideView(self, root: TreeNode):
res=[]
if not root:
return res
queue=[root]
while queue:
new=[]
for i in queue:
if i.left:
new.append(i.left)
if i.right:
new.append(i.right)
res.append(queue[-1].val)
queue=new
return res
还是按照3的模板,输出res的最后一个元素的第一个元素。
def findBottomLeftValue(self, root: TreeNode) :
res=[]
def helper(root,depth):
if not root:
return
if len(res)==depth:
res.append([])
res[depth].append(root.val)
helper(root.left,depth+1)
helper(root.right,depth+1)
helper(root,0)
return res[-1][0]
def largestValues(self, root: TreeNode) :
res,num=[],[]
def helper(root,depth):
if not root:
return
if len(res)==depth:
res.append([])
res[depth].append(root.val)
helper(root.left,depth+1)
helper(root.right,depth+1)
helper(root,0)
for res_num in res:
num.append(max(res_num))
return num
def averageOfLevels(self, root: TreeNode):
res=[]
def helper(root,depth):
if not root:
return res
if len(res)==depth:
res.append([])
res[depth].append(root.val)
helper(root.left,depth+1)
helper(root.right,depth+1)
helper(root,0)
num=[]
for res_each in res:
num.append(sum(res_each)/len(res_each))
return num
def deepestLeavesSum(self, root: TreeNode) :
res=[]
def helper(root,depth):
if not root:
return res
if len(res)==depth:
res.append([])
res[depth].append(root.val)
helper(root.left,depth+1)
helper(root.right,depth+1)
helper(root,0)
return sum(res[-1])
关于前中后遍历可以参看博文面试基本数据结构和算法
def preorder(self, root: 'Node') :
if not root:
return []
result,stack=[],[root]
while stack:
root=stack.pop()
result.append(root.val)
if root.children:
for idx in range(len(root.children)-1,-1,-1):
stack.append(root.children[idx])
return result
def postorder(self, root: 'Node') :
if not root:
return []
stack,res=[root],[]
while stack:
node=stack.pop()
res.append(node.val)
if node.children:
stack.extend(node.children)
return res[::-1]
def constructFromPrePost(self, pre: List[int], post: List[int]) :
if not pre:
return None
root=TreeNode(pre[0])
if len(pre)==1:
return root
n=post.index(pre[1])
root.left=self.constructFromPrePost(pre[1:n+2],post[:n+1])
root.right=self.constructFromPrePost(pre[n+2:],post[n+1:-1])
return root
def buildTree(self, inorder: List[int], postorder: List[int]) :
if not postorder:
return None
x=postorder.pop(len(postorder)-1)
node=TreeNode(x)
i=inorder.index(x)
node.left=self.buildTree(inorder[:i],postorder[:i])
node.right=self.buildTree(inorder[i+1:],postorder[i:])
return node
def buildTree(self, preorder: List[int], inorder: List[int]) :
if not preorder:
return None
x=preorder.pop(0)
node=TreeNode(x)
i=inorder.index(x)
node.left=self.buildTree(preorder[:i],inorder[:i])
node.right=self.buildTree(preorder[i:],inorder[i+1:])
return node
def bstFromPreorder(self, preorder: List[int]) :
if not preorder:
return None
root=TreeNode(preorder[0])
left,right=[],[]
for x in preorder[1:]:
if x<root.val:
left.append(x)
else:
right.append(x)
root.left=self.bstFromPreorder(left)
root.right=self.bstFromPreorder(right)
return root
def findSecondMinimumValue(self, root: TreeNode):
def inOrder(self, root:TreeNode):
res = []
if(root != None):
res = res + self.inOrder(root.left)
res.append(root.val)
res = res + self.inOrder(root.right)
return res
listNode = set(self.inOrder(root))
sortedNode = sorted(listNode)
if(len(listNode) == 1):
return -1
else:
return sortedNode[1]
def kthSmallest(self, root: TreeNode, k: int) :
lst =[]
def get(r):
if r is not None:
get(r.left)
lst.append(r.val)
get(r.right)
return lst
lst_n = get(root)
return lst_n[k-1]
def pruneTree(self, root: TreeNode):
if not root:
return None
root.left=self.pruneTree(root.left)
root.right=self.pruneTree(root.right)
if root.val==0 and not root.left and not root.right:
return None
return root
def sortedArrayToBST(self, nums: List[int]) :
if not nums:
return None
else:
mid=len(nums)//2
node=TreeNode(nums[mid])
node.left=self.sortedArrayToBST(nums[:mid])
node.right=self.sortedArrayToBST(nums[mid+1:])
return node
def flatten(self, root: TreeNode) : """ Do not return anything, modify root in-place instead. """ def helper(root): if root == None: return helper(root.left) helper(root.right) if root.left != None: # 后序遍历 pre = root.left # 令 pre 指向左子树 while pre.right: pre = pre.right # 找到左子树中的最右节点 pre.right = root.right # 令左子树中的最右节点的右子树 指向 根节点的右子树 root.right = root.left # 令根节点的右子树指向根节点的左子树 root.left = None # 置空根节点的左子树 root = root.right # 令当前节点指向下一个节点 helper(root)
def connect(self, root: 'Node'):
if not root:
return
if root.left:
root.left.next = root.right
if root.next:
root.right.next = root.next.left
self.connect(root.left)
self.connect(root.right)
return root
这个跟前一题的主要区别是这里的空指针也被标注出来了,所以还要加上空指针的检测和处理。
def connect(self, root: 'Node'): if not root: return None queue = [root] while queue: next_queue = [] for i in range(len(queue)): if queue[i].left: next_queue.append(queue[i].left) if queue[i].right: next_queue.append(queue[i].right) if i < len(queue) - 1: queue[i].next = queue[i + 1] queue = next_queue return root
def invertTree(self, root: TreeNode):
if not root:
return None
root.left,root.right=self.invertTree(root.right),self.invertTree(root.left)
return root
def serialize(self, root: TreeNode): #Encodes a tree to a single string. def preorder(root): out=[] if root: out+=[str(root.val)] out+=preorder(root.left) out+=preorder(root.right) return out return ','.join(preorder(root)) def deserialize(self, data: str): #Decodes your encoded data to tree. if not data: return None def buildTree(pre_o, in_o): if not pre_o: return None mid = pre_o[0] i = in_o.index(mid) root = TreeNode(mid) root.left = buildTree(pre_o[1:i + 1], in_o[:i]) root.right = buildTree(pre_o[i + 1:], in_o[i + 1:]) return root pre_o = list(map(int, data.split(','))) in_o = sorted(pre_o) return buildTree(pre_o, in_o)
这道题的思路是找到右子树中的最小值,将要删除的节点替换为该值,然后在右子树中删除最小的那个节点。
def deleteNode(self, root: TreeNode, key: int): if not root: return None if root.val>key: root.left=self.deleteNode(root.left,key) elif root.val<key: root.right=self.deleteNode(root.right,key) else: if not root.left or not root.right: root=root.left if root.left else root.right else: cur=root.right while cur.left: cur=cur.left root.val=cur.val root.right=self.deleteNode(root.right,cur.val) return root
def getMinimumDifference(self, root: TreeNode):
def inorder(node):
if not node:
return []
return inorder(node.left)+[node.val]+inorder(node.right)
res=99999999
l=inorder(root)
for i in range(1,len(l)):
res=min(res,l[i]-l[i-1])
return res
def convertBST(self, root: TreeNode):
def rdl(self,root,preans=0):
if root is None:
return preans
root.val+=self.rdl(root.right,preans)
return self.rdl(root.left,root.val)
rdl(root)
return root
def findTilt(self, root: TreeNode):
ret = [0]
def tile(node):
if not node:return 0
left = tile(node.left)
right = tile(node.right)
ret[0] += abs(left - right)
return left + right + node.val
tile(root)
return ret[0]
def diameterOfBinaryTree(self, root: TreeNode) :
self.R=0
self.dfs(root)
return self.R
def dfs(self,root):
if not root:
return 0
l=self.dfs(root.left)
r=self.dfs(root.right)
self.R=max(l+r,self.R)
return max(l,r)+1
def sumOfLeftLeaves(self, root: TreeNode) :
if root==None:
return 0
if root.left and root.left.left==None and root.left.right==None:
return root.left.val+self.sumOfLeftLeaves(root.right)
else:
return self.sumOfLeftLeaves(root.left)+self.sumOfLeftLeaves(root.right)
def trimBST(self, root: TreeNode, L: int, R: int) :
if not root:
return None
root.left = self.trimBST(root.left, L, R)
root.right = self.trimBST(root.right, L, R)
if root.val < L:
return root.right
if root.val > R:
return root.left
return root
def findDuplicateSubtrees(self, root: TreeNode):
ans, d = [], {}
def f(r):
if not r:
return ' '
s = str(r.val) + f(r.left) + f(r.right)
if s not in d:
d[s] = True
elif d[s]:
ans.append(r)
d[s] = False
return s
f(root)
return ans
def mergeTrees(self, t1: TreeNode, t2: TreeNode):
if t1 and t2:
t1.val+=t2.val
t1.left=self.mergeTrees(t1.left,t2.left)
t1.right=self.mergeTrees(t1.right,t2.right)
return t1
return t1 or t2
def tree2str(self, t: TreeNode):
if not t:
return ""
if not t.left and not t.right:
return str(t.val)
result=str(t.val)
if t.left:
result+="("+self.tree2str(t.left)+")"
else:
result+="()"
if t.right:
result+="("+self.tree2str(t.right)+")"
return result
def searchBST(self, root: TreeNode, val: int) :
if not root:
return None
if root.val==val:
return root
if root.val>val:
return self.searchBST(root.left,val)
else:
return self.searchBST(root.right,val)
def rangeSumBST(self, root: TreeNode, L: int, R: int) -> int:
self.sum=0
def range(self,root,L,R):
if not root:
return None
self.range(root.left,L,R)
if root.val<=R and root.val>=L:
self.sum+=root.val
self.range(root.right,L,R)
range(root,L,R)
return self.sum
def minDepth(self, root: TreeNode):
if not root:
return 0
if root.left is None or root.right is None:
return 1+max(self.minDepth(root.left),self.minDepth(root.right))
else:
return 1+min(self.minDepth(root.left),self.minDepth(root.right))
def maxDepth(self, root: 'Node'):
if not root:
return 0
if not root.children:
return 1
return max(self.maxDepth(child)+1 for child in root.children)
def printTree(self, root: TreeNode): h=0 def f(r,i): if not r: return nonlocal h h=max(h,i) f(r.left,i+1) f(r.right,i+1) f(root,0) n=2**(h+1)-1 a=[['']*n for _ in range(h+1)] def g(r,i,j): if not r: return a[i][j]=str(r.val) s=(2**(h-i)-1)//2+1 g(r.left,i+1,j-s) g(r.right,i+1,j+s) g(root,0,n//2) return a
def isValidBST(self, root: TreeNode) :
inorder=self.inorder(root)
return inorder==list(sorted(set(inorder)))
def inorder(self,root):
if not root:
return []
return self.inorder(root.left)+[root.val]+self.inorder(root.right)
def recoverTree(self, root: TreeNode):
point=[]
val=[]
def inorder(root):
if not root:
return
inorder(root.left)
point.append(root)
val.append(root.val)
inorder(root.right)
return
inorder(root)
val=sorted(val)
for i in range(len(point)):
point[i].val=val[i]
def binaryTreePaths(self, root: TreeNode):
if not root:
return []
if not root.left and not root.right:
return [str(root.val)]
paths=[]
if root.left:
for i in self.binaryTreePaths(root.left):
paths.append(str(root.val)+'->'+i)
if root.right:
for i in self.binaryTreePaths(root.right):
paths.append(str(root.val)+'->'+i)
return paths
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') :
if not root or root==p or root==q:
return root
left=self.lowestCommonAncestor(root.left,p,q)
right=self.lowestCommonAncestor(root.right,p,q)
if not left and not right:
return None
elif left and right:
return root
else:
if not left:
return right
else:
return left
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode'):
if p.val<root.val and q.val<root.val:
return self.lowestCommonAncestor(root.left,p,q)
if p.val>root.val and q.val>root.val:
return self.lowestCommonAncestor(root.right,p,q)
return root
def findFrequentTreeSum(self, root: TreeNode) -> List[int]: d={} def fun(node): if not node:return if node.left: fun(node.left) node.val+=node.left.val if node.right: fun(node.right) node.val+=node.right.val d[node.val]=d.get(node.val,0)+1 fun(root) if not d:return [] m=max(d.values()) return [k for k,v in d.items() if v==m]
def findFrequentTreeSum(self, root: TreeNode) : d={} def fun(node): if not node:return if node.left: fun(node.left) node.val+=node.left.val if node.right: fun(node.right) node.val+=node.right.val d[node.val]=d.get(node.val,0)+1 fun(root) if not d:return [] m=max(d.values()) return [k for k,v in d.items() if v==m]
def maxDepth(self, root: TreeNode) :
if not root :
return 0
else:
return 1+max(self.maxDepth(root.left),self.maxDepth(root.right))
def sumNumbers(self, root: TreeNode) :
def helper(root,sum):
if not root:
return 0
sum=sum*10
sum+=root.val
if root.left is None and root.right is None:
return sum
else:
return helper(root.left,sum)+helper(root.right,sum)
return helper(root,0)
在树的题目中,会有一些特殊要求或者特殊结构的树,也需要注意下。
def leafSimilar(self, root1: TreeNode, root2: TreeNode): def getleaf(self,root,res): if not root: return res if not root.left and not root.right: res.append(root.val) if root.left: self.getleaf(root.left,res) if root.right: self.getleaf(root.right,res) return res leaves1=getleaf(root1,[]) leaves2=getleaf(root2,[]) if str(leaves1)==str(leaves2): return True else: return False
def isUnivalTree(self, root: TreeNode):
res=[]
def inorder(self,root):
if not root:
return True
inorder(root.left)
res.append(root.val)
inorder(root.right)
inorder(root)
return True if len(set(res))==1 else False
def constructMaximumBinaryTree(self, nums: List[int]):
if not nums:
return
max_num=max(nums)
max_num_index=nums.index(max_num)
root=TreeNode(max_num)
root.left=self.constructMaximumBinaryTree(nums[:max_num_index])
root.right=self.constructMaximumBinaryTree(nums[max_num_index+1:])
return root
def isBalanced(self, root: TreeNode) :
if not root:
return True
if abs(self.depth(root.left)-self.depth(root.right))>1:
return False
return self.isBalanced(root.left) and self.isBalanced(root.right)
def depth(self,root):
if not root:
return 0
return max(self.depth(root.left),self.depth(root.right))+1
def isSymmetric(self, root: TreeNode):
if not root:
return True
else:
return self.childTreeIsSymmetric(root.left,root.right)
def childTreeIsSymmetric(self,p,q):
if not p or not q:
return p==q
if p.val!=q.val:
return False
return self.childTreeIsSymmetric(p.left,q.right) and self.childTreeIsSymmetric(p.right,q.left)
def findTarget(self, root: TreeNode, k: int): if not root: return False # 深度优先搜索 def dfs(node): # target目标值与当前值求差 if k - node.val in exist: self.res = True return else: exist.add(node.val) # 当前没有符合调条件的数据,继续 if not self.res: if node.left: dfs(node.left) if node.right: dfs(node.right) exist = set() self.res = False dfs(root) return self.res
def isSameTree(self, p: TreeNode, q: TreeNode) :
if not p and not q:
return True
elif p is not None and q is not None:
if p.val==q.val:
return self.isSameTree(p.left,q.left) and self.isSameTree(p.right,q.right)
else:
return False
else:
return False
def isSubtree(self, s: TreeNode, t: TreeNode):
if not s:
return False
return self.isSame(s,t) or self.isSubtree(s.left,t) or self.isSubtree(s.right,t)
def isSame(self,s,t):
if s and t:
return s.val==t.val and self.isSame(s.left,t.left) and self.isSame(s.right,t.right)
elif s==t:
return True
else:
return False
def numTrees(self, n: int) :
dp = [0] * (n+1)
dp[0] = 1
dp[1] = 1
for i in range(2,n+1):
for j in range(1,i+1):
dp[i] += dp[j-1] * dp[i-j]
return dp[n]
def generateTrees(self, n: int): def generate_trees(start, end): if start > end: return [None,] all_trees = [] for i in range(start, end + 1): # pick up a root # all possible left subtrees if i is choosen to be a root left_trees = generate_trees(start, i - 1) # all possible right subtrees if i is choosen to be a root right_trees = generate_trees(i + 1, end) # connect left and right subtrees to the root i for l in left_trees: for r in right_trees: current_tree = TreeNode(i) current_tree.left = l current_tree.right = r all_trees.append(current_tree) return all_trees return generate_trees(1, n) if n else []
def isSymmetric(self, root: TreeNode):
if not root:
return True
else:
return self.childTreeIsSymmetric(root.left,root.right)
def childTreeIsSymmetric(self,p,q):
if not p or not q:
return p==q
if p.val!=q.val:
return False
return self.childTreeIsSymmetric(p.left,q.right) and self.childTreeIsSymmetric(p.right,q.left)
def rob(self, root: TreeNode):
def helper(root):
if not root:
return [0,0]
left=helper(root.left)
right=helper(root.right)
rob=root.val+left[1]+right[1]
skip=max(left)+max(right)
return [rob,skip]
res=helper(root)
return max(res)
def maxPathSum(self, root: TreeNode) :
self.max = float('-inf')
self.max_path(root)
return self.max
def max_path(self, root):
if not root: return 0
left = self.max_path(root.left)
right = self.max_path(root.right)
self.max = max(left + right + root.val, self.max)
tmp = max(left, right) + root.val
return tmp if tmp > 0 else 0
def hasPathSum(self, root: TreeNode, sum: int) :
if not root :
return False
if not root.left and not root.right and root.val==sum:
return True
return self.hasPathSum(root.left,sum-root.val) or self.hasPathSum(root.right,sum-root.val)
def pathSum(self, root: TreeNode, sum: int) :
res=[]
if not root:
return []
def helper(root,sum,tmp):
if not root:
return
if not root.left and not root.right and root.val==sum:
tmp+=[root.val]
res.append(tmp)
return
helper(root.left,sum-root.val,tmp+[root.val])
helper(root.right,sum-root.val,tmp+[root.val])
helper(root,sum,[])
return res
class Solution:
def pathSum(self, root: TreeNode, sum: int) :
if not root:
return 0
return self.pathSum(root.left,sum)+self.pathSum(root.right,sum)+self.dfs(root,sum)
def dfs(self,node,sum):
if not node:
return 0
count=0
if node.val==sum:
count=1
return count+self.dfs(node.left,sum-node.val)+self.dfs(node.right,sum-node.val)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。