Leetcode 112 路径总和
又是一道二叉树的题目,这次我们来总结二叉树的深度搜索,广度搜索:
二叉树的遍历
- 广度优先遍历breadth first traversal:又称层次遍历,从树的根节点(root)开始,从上到下,从左到右遍历整个树的节点。
- 深度优先遍历depth first traversal:对于一颗二叉树,深度优先遍历是沿着树的深度遍历树的节点,尽可能深的搜索树的分支。
- 深度优先遍历有重要的三种方法。这三种方式常被用于访问树的节点,它们之间的不同在于访问每个节点的次序不同。
- 先序遍历(preorder):根节点->左子树->右子树,
- 中序遍历(inorder):左子树->根节点->右子树,
- 后序遍历(postorder):左子树->右子树->根节点。
我们以这幅图为例子进行分析三种遍历的区别。
- 层次遍历(BFS):0123456789
- 先序遍历:0137849256(根左右)
- 中序遍历:7381940526(左中右)
- 后序遍历:7839415620(左右中)
# 先序遍历
def preorder(self, root):
if not root:
return
print(root.val) # 取出来值!!
self.preorder(node.left)
self.preorder(node.right)
# 中序遍历
def inorder(self, root):
if not root:
return
self.inorder(root.left)
print(root.val) # 取出来值!!
self.inorder(root.right)
# 后序遍历
def postorder(self, root):
if not root:
return
self.postorder(root.left)
self.postorder(root.right)
print(root.val) ## 取出来值
# 广度优先(层次)遍历
def levelOrder(self,root):
if not root:
return
queue = collections.deque()
queue.append(root)
while queue:
node = queue.popleft()
# 进行相关操作
print(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
更新2020.03.30 DFS的非递归方法
#非递归实现前序遍历
# 先序遍历是先访问节点,然后再将节点入栈
def preOrderNonRec(root):
if not root:
return
stack = []
cur = root
while cur or stack:
while cur:
print(cur.val)
stack.append(cur)
cur = cur.left #一直往下找左子树
cur = stack.pop()
cur = cur.right
# 中序遍历是先入栈,然后节点弹出栈后再访问。
def midOrderNonRec(root):
if not root:
return
stack = []
cur = root
while cur or stack:
while cur:
stack.append(cur)
cur = cur.left #一直往下找左子树
cur = stack.pop()
print(cur.val)
cur = cur.right
#非递归实现后序遍历
'''
在这种遍历中,每个根节点都要经过三次:
第一次遇到它时要立即转去处理其左子树,
第二次从左子树经由它转去处理右子树,
第三次从右子树回来才应该处理根节点数据,然后返回上一层。
'''
def postOrderNonRec(root):
if not root:
return
stack = []
cur = root
while cur or stack:
while cur:
stack.append(cur)
if cur.left:
cur = cur.left
else:
cur = cur.right
cur = stack.pop()
print(cur.val)
if stack and stack[-1].left == cur: #栈不空且当前节点是栈顶的左子节点,那么应当继续去访问栈顶的右子节点
cur = stack[-1].right
else:
cur = None #没有右子树或右子树遍历完毕,强迫退栈
'''
也可以反转前序遍历的方式实现,因为后序是右->左->中,先序是中->左->右
'''
def postorderTraversal(self, root):
ans, queue, cur = [], [], root
while queue or cur:
while cur:
queue.append(cur)
ans.append(cur.val)
cur = cur.right
cur = queue.pop()
cur = cur.left
return ans[::-1]
Leetcode 112 路径总和
又是一道二叉树的题目,这次我们来总结二叉树的深度搜索,广度搜索:
介绍完搜索,切入正题,leetcode112 题路径总和
显然这是一个深度优先的算法的题目。需要按照深度遍历整个树。
依然按照递归思想求解。设置递归的条件,root
节点的左右子节点都None
时判断整个路径和是否单组要求。
class Solution(object):
def hasPathSum(self, root, sum):
"""
:type root: TreeNode
:type sum: int
:rtype: bool
"""
if not root:
return False
sum -= root.val
if not root.right and not root.left: ## 搜索到了底部
return sum == 0
return self.hasPathSum(root.right,sum) or self.hasPathSum(root.left,sum)
# 继续在两侧进行搜索
其实,做为树的递归题目是非常有套路可循的,因为树有两个分支,所以在递归里也有两个分支,一般是通过right == None and left == None
和right or left
来实现分支的。只要明白了这一点,递归函数就不会很难设计。