版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/dpengwang/article/details/87998680
求二叉树中的一条路径,使其路径和为定值,该路径必须是从上往下的
基本的思路就是遍历二叉树中的每个点,然后再求以该点为出发点的所有路径
如方法1,方法2
方法1 双递归
外层递归遍历所有点,内层递归遍历以该点为起点的所有路径
class Solution1:
def pathSum(self, root, sum):
"""
:type root: TreeNode
:type sum: int
:rtype: int
"""
if root == None:
return 0
else:
res = 0
if root.right:
res += self.pathSum(root.right, sum)
res += self.getres(root, sum)
if root.left:
res += self.pathSum(root.left, sum)
return res
def getres(self, root, sumer):
if root == None:
return 0
else:
res = 0
if root.val == sumer:
res +=1
if root.left:
res += self.getres(root.left, sumer-root.val)
if root.right:
res +=self.getres(root.right, sumer-root.val)
return res
方法2 递归法的非递归形式
用一个栈非递归遍历二叉树的所有点,另一个栈非递归遍历所有路径
因为外层递归只要遍历到所有点即可,所以不用考虑入栈的顺序
class Solution2:
#非递归无序遍历二叉树,然后对每个节点进行路径查找
def pathSum(self, root, sum):
res = 0
if root == None:
return 0
stack = [root]
while(len(stack)):
node = stack.pop()
res += self.getres(node, sum)
if node.left:
stack.append(node.left)
if node.right:
stack.append(node.right)
return res
def getres(self, root, sum):
stack = [[root,sum]]
res = 0
while(len(stack)):
node,sumer = stack.pop()
if node.val == sumer:
res +=1
if node.left:
stack.append([node.left, sumer-node.val])
if node.right:
stack.append([node.right, sumer-node.val])
return res
class Solution3:
#先序遍历,再对每个节点进行递归查路径
def pathSum(self, root, sum):
res = 0
if root == None:
return 0
stack = [root]
while(len(stack)):
node = stack.pop()
res += self.getres(node, sum)
if node.left:
stack.append(node.left)
if node.right:
stack.append(node.right)
return res
def getres(self, root, sum):
stack = [[root,sum]]
res = 0
while(len(stack)):
node,sumer = stack.pop()
if node.val == sumer:
res +=1
if node.left:
stack.append([node.left, sumer-node.val])
if node.right:
stack.append([node.right, sumer-node.val])
return res
方法3 后续遍历加dict
上面两种方法中,对于二叉树的节点都有大量重复的访问和计算,时间复杂度为
,我们可以利用二叉树的后续遍历和一个字典来实现o(n)时间复杂度
核心思想
- 后续遍历二叉树。对于每个节点,第一次遍历到他时,记录根节点到其路径,加入字典,第二次遍历到他时,即访问他时,判断该点对应的路径和减去sum在字典中出现的次数及路径的条数
- 要注意的是,每次从一个节点的左子树转到右子树时,要将左子树节点对应的路径和从字典中删除
- 字典的初始值设为{0:1}
- 对于sum为0的情况,要将字典中的value减去1(减去自己)
class Solution4:
def pathSum(self, root, sum):
if root == None:
return 0
from collections import defaultdict
dictionary = defaultdict(int)
dictionary[0] =1
pNode, curr_sum, stack,res, prev = root, 0, [], 0, None
while(len(stack) or pNode):
print(dictionary)
if pNode:
curr_sum += pNode.val
stack.append([pNode, curr_sum])
dictionary[curr_sum] +=1
pNode = pNode.left
else:
pNode,curr_sum = stack[-1]
if pNode.right == None or pNode.right == prev:
res += dictionary[curr_sum - sum]
if sum ==0:
res -=1
dictionary[curr_sum] -=1
stack.pop()
prev = pNode
pNode = None
else:
pNode = pNode.right
return res