题目
1022. 从根到叶的二进制数之和
给出一棵二叉树,其上每个结点的值都是 0 或 1 。每一条从根到叶的路径都代表一个从最高有效位开始的二进制数。
例如,如果路径为 0 -> 1 -> 1 -> 0 -> 1,那么它表示二进制数 01101,也就是 13 。
对树上的每一片叶子,我们都要找出从根到该叶子的路径所表示的数字。
返回这些数字之和。题目数据保证答案是一个 32 位 整数。
示例 1:
输入:root = [1,0,1,0,1,0,1]
输出:22
解释:(100) + (101) + (110) + (111) = 4 + 5 + 6 + 7 = 22
示例 2:
输入:root = [0]
输出:0
提示:
树中的节点数在 [1, 1000] 范围内
Node.val 仅为 0 或 1
解法
方法1:递归
int res;
public int sumRootToLeaf(TreeNode root) {
dfs(root, new ArrayList<>());
return res;
}
public void dfs(TreeNode root, List<Integer> paths) {
paths.add(root.val);
if (root.left == null && root.right == null) {
res += cal(paths);
return;
}
if (root.left != null) {
dfs(root.left, paths);
paths.remove(paths.size() - 1);
}
if (root.right != null) {
dfs(root.right, paths);
paths.remove(paths.size() - 1);
}
}
private int cal(List<Integer> paths) {
int t = 0, n = paths.size();
for (int i = 0; i < n; i++) {
t |= paths.get(i) << (n - i - 1);
}
return t;
方法2:递归
public int sumRootToLeaf(TreeNode root) {
return dfs(root, 0);
}
public int dfs(TreeNode root, int res) {
if (root == null) return 0;
//res左移一位,让出低位给root.val
res = res << 1 | root.val;
if (root.left == null && root.right == null) {
return res;
}
return dfs(root.left, res) + dfs(root.right, res);
}
方法3:迭代
迭代的思路不如递归好写
public int sumRootToLeaf(TreeNode root) {
Deque<TreeNode> stk = new ArrayDeque<>();
int t = 0, res = 0;
//prev记录上一轮访问过的节点
TreeNode prev = null;
while (!stk.isEmpty() || root != null) {
while (root != null) {
//计算
t = t << 1 | root.val;
//左孩子一直进栈,直到没有左孩子
stk.push(root);
root = root.left;
}
//看下当前栈顶的节点
root = stk.peek();
//
if (root.right == null || root.right == prev) {
//收集的条件
if (root.left == null && root.right == null) {
res += t;
}
//恢复,弹出,记录prev
t >>= 1;
stk.pop();
prev = root;
root = null;//标记
} else {
root = root.right;
}
}
return res;
}