Day 23:二元树分支总和 sums of the branches

今天这题题目是国外论坛分享的面试题
其实也是LeetCode-Path Sum的衍生题,直接来刷题吧!

简单复习一下二元树 Binary Tree 的特点:

  1. 可以为空
  2. 0 ≤ Node's Degree ≤ 2
  3. 子树有左右方向之区分

还记得Day 19:二元树遍历 Binary Tree Traversal我们提到的三种追踪方式吗?
今天我们会用到
前序追踪(preOrder) “中左右”的方式还解决这题问题!

假设以下是我们一开始的树
https://ithelp.ithome.com.tw/upload/images/20211008/20141729j8xifPRnXG.png

先思考一下,如果我们要获得这棵树的所有树枝的加总,我们应该要怎麽做?
我们应该要拜访每一个节点(node)对吧?
那要用哪一种方式呢?depth-first-search-like?

我们拜访每一个节点的时候去把每个拜访过的节点的值加起来。
我们知道,在二元树的结构中,是有左右之分的,也就是每个节点都有可能有左右儿子。
这种重复性的结构我们应该想到用递回的方式。

没错我们其实就只用建立一个递回方法,把我们目前计算的结果存到array依序往左右儿子传递,直到左右儿子已经没有後代就停止计算。

就像下面这张图
在一开始初始化sum = 0
如第一次的答案 → 粉红色1的路径开始往下把拜访过的数加总到sum,
走访的路径像是

5 → 哇5的左手牵着4 → 还没完唷 4 的左手还拉着11 → 11左手又有 7 → 确定左边没了 → 回去11 发现右手还有9 在把暂存的+9 → 9没有左右手了 → 退回4 ....这样的走访路径

https://ithelp.ithome.com.tw/upload/images/20211008/20141729PcZKG0iQcC.png

时间复杂度: O(n) 因为我们需要走访每个node 没个动作也只需要简单的加总
空间复杂度: O(n) 为什麽呢?我们可以简单说因为我们不可能获得超过n的branch

我们来深入了解一下为什麽?
在范例中我们可以观察到,答案的数量应该会跟完全没有左右小孩的节点一样多,在树中我们叫做叶子(leaf)。
这张图我们可以观察到:当二元树每一层都长满的时候,下一层的节点数都恰好会是上一层的两倍。
而所有的节点树恰好就是 2^n层 -1
而最後一层的节点树会是 2^ n-1
我们每次用来储存结果的list大概就是为後一层的节点树,也就是 2^ (n-1)
而节点的总数N = 2^n -1
所以 2^ (n-1) = (N+1) / 2
如果 N 趋近无限大时,我们可以说,最後一层的节点树就会大约是一半的总节点树。

可以参考下面来思考看看!

https://ithelp.ithome.com.tw/upload/images/20211008/20141729NhP0ijp4PD.png

那我们来实作吧!

class BinaryTree {
  constructor(value) {
    this.value = value;
    this.left = null;
    this.right = null;
  }
}

function branchSums(root) {
  const sum = [];
  getBranchSums(root, 0, sum);
  return sum;
}

//递回function
function getBranchSums(node, tmpSum, sum) {
  //一开始检查是否为节点 不是就停止递回呼叫
  if (!node) return;
  const currentSum = tmpSum + node.value;
  //如果左右都没有节点了 答案放入sum
  if (!node.left && !node.right) {
    sum.push(currentSum);
    return;
  }

  //呼叫自己
  getBranchSums(node.left, currentSum, sum);
  getBranchSums(node.right, currentSum, sum);
}

明日题目预告:一起来实作min-heap吧! Min-Heap construction


<<:  Day24 jQuery 基本教学(四)

>>:  Day 26 - 你有没有玩过LOL、特、CS、SF、枫之谷、APEX?

(Day 21) ES6 class 语法糖

前言 前面有花几篇介绍了,原型链以及使用建构式、以及使用 Object.create() 建立多层原...

DAY7:Kaggle-San Francisco Crime Classification(下)

资料视觉化 这边我们会用到seaborn来做一下简单的资料视觉化。 import seaborn ...

产品设计框架 - 双钻石产品设计法 Double Diamond

双钻石产品设计法,是由英国设计协会(Design Council)在2005年提出的设计流程,主要有...

Day28 传播链程序实作

今天要来设计一种算法来查找从一个人到另一个人的病毒链,可以算是复习前面的for回圈,及swap的应用...

总结

从学校毕业到现在,我认为最重要的是能够自我规律的去学习自己想学的事物,藉由不同的活动来提升自己能力。...