一、Problem
給出一棵二叉樹,其上每個結點的值都是 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 。
二、Solution
方法一:回溯
思路
到達葉子結點的時候結算即可,結算完畢需要將該葉子結點的值的貢獻抹掉;而且當以某一個結點 node 爲根的子樹遍歷完成後,該 node 的貢獻也抹掉
class Solution {
int sum, x, rVal;
void dfs(TreeNode root) {
if (root.left == null && root.right == null) {
x = (x << 1) | root.val;
sum += x;
x = x >>> 1;
return;
}
x = (x << 1) + root.val;
if (root.left != null) dfs(root.left);
if (root.right != null) dfs(root.right);
x = x >>> 1;
}
public int sumRootToLeaf(TreeNode root) {
rVal = root.val;
dfs(root);
return sum;
}
}
x = (x << 1) + root.val
,這句話可以改爲 x = (x << 1) | root.val
,因爲 root.val 爲 0/1
複雜度分析
- 時間複雜度:,
- 空間複雜度:,
上面的方法我們是自己寫邏輯進行回溯,然兒沒有利用遞歸的自帶回溯,如果用了的話,代碼會更簡潔,但我覺得上面的代碼比較易懂…
class Solution {
int dfs(TreeNode root, int x) {
if (root == null)
return 0;
x = (x << 1) | root.val;
if (root.left == null && root.right == null)
return x;
return dfs(root.left, x) + dfs(root.right, x);
}
public int sumRootToLeaf(TreeNode root) {
return dfs(root, 0);
}
}