题目介绍
描述:
给出一棵二叉树,其上每个结点的值都是 0 或 1 。每一条从根到叶的路径都代表一个从最高有效位开始的二进制数。例如,如果路径为 0 -> 1 -> 1 -> 0 -> 1,那么它表示二进制数 01101,也就是 13 。
对树上的每一片叶子,我们都要找出从根到该叶子的路径所表示的数字。
以 10^9 + 7 为模,返回这些数字之和。
输入:[1,0,1,0,1,0,1]
输出:22
解释:(100) + (101) + (110) + (111) = 4 + 5 + 6 + 7 = 22
提示:
树中的结点数介于 1 和 1000 之间。
node.val 为 0 或 1 。
解题思路:
递归算法的关键是要明确函数的「定义」是什么,然后相信这个定义,利用这个定义推导最终结果。
写树相关的算法,简单说就是,先搞清楚当前 root 节点该做什么,然后根据函数定义递归调用子节点,递归调用会让孩子节点做相同的事情。
二叉树题目的一个难点在于如何通过题目的要求思考出每一个节点需要做什么
二叉树解题策略
一 递归 二 队列 + 迭代 (层次遍历) 三 栈 + 迭代 (非递归遍历) 四 其它
三种基本的遍历方式,都可以用递归来实现。写递归算法的时候,需要注意递归退出条件以及递归操作的表达。
参看题目,采取DFS比较适合。第一步,找出每一个根到叶的路径,第二步把这个数字转换成二进制。Python有个bin函数可以实现十进制转换为二进制。
自己的解法实现
def sumRootToLeaf(self, root):
if not root: return 0
self.res = 0
def dfs(node, num):
if not node: return
num = (num << 1) + node.val
if not node.left and not node.right:
self.res += num
return
dfs(node.left, num)
dfs(node.right, num)
dfs(root, 0)
return self.res
网上比较优秀的解法
解法一
def sumRootToLeaf2(self, root):
def dfs(node, n):
if not node: return 0
n = n*2 + node.val
if not node.left and not node.right:
return n
return (dfs(node.left, n) + dfs(node.right, n)) % (10**9 + 7)
return dfs(root, 0)
解法二
DFS深度优先
def sumRootToLeaf3(self, root):
if not root: return 0
stack, res = [(root, root.val)], 0
while stack:
node, num = stack.pop()
if not node.left and not node.right:
res += num
if node.right:
stack.append((node.right, (num << 1) + node.right.val))
if node.left:
stack.append((node.left, (num << 1) + node.right.val))
return res % (10**9 + 7)
解法三
BFS广度优先
def sumRootToLeaf4(self, root):
from collections import deque
queue = deque([(root, 0)]) # 注意这里0与上面栈区别
res = 0
while queue:
for _ in range(len(queue)):
node, val = queue.popleft()
num = val * 2 + node.val # 因为初始是0,并没有加上本身节点的val
if not node.left and not node.right:
res += num
if node.left:
queue.append((node.left, num))
if node.right:
queue.append((node.right, num))
return res % (10**9 + 7)
相关知识总结和思考
相关知识:
BFS:广度/宽度优先。其实就是从上到下,先把每一层遍历完之后再遍历一下一层。
可以使用Queue的数据结构。我们将root节点初始化进队列,通过消耗尾部,插入头部的方式来完成BFS。
二叉搜索树(BST)的特性:
- 若它的左子树不为空,则所有左子树上的值均小于其根节点的值
- 若它的右子树不为空,则所有右子树上的值均大于其根节点的值
- 它的左右子树也分别为二叉搜索树
递归与迭代的区别
递归:重复调用函数自身实现循环称为递归; 迭代:利用变量的原值推出新值称为迭代,或者说迭代是函数内某段代码实现循环;