【发布时间】:2022-11-11 05:27:00
【问题描述】:
我最近被要求解决与二叉树遍历相关的问题,其目的是找到二叉树中所有节点的总和,其中节点为奇数,其叔叔也是奇数。我提出了一个解决方案,其算法复杂度为 O(n)(树的 1 次完全遍历),辅助内存使用量等于 O(h)。当且仅当二叉树恰好是 BST 并且高度平衡时,那么可以说辅助内存复杂度将为 O(log(n))。
我的解决方案是所有根到叶问题的路径识别的变体。可以在此处找到此问题及其解决方案。
https://github.com/anandkulkarnisg/BinaryTree/blob/main/set2/rootleaf.cpp
这里给出了奇叔的奇节点的解决方案。
https://github.com/anandkulkarnisg/BinaryTree/blob/main/set5/sumodduncle.cpp
面试官同意算法的复杂性是显而易见的,因为肯定需要一次遍历,它是 O(n)。但他认为辅助存储器的复杂性可以设计得比 O(h) 好得多,他没有说明这种方法是什么。我已经考虑了 2 周了,但还没有更好的解决方案。
顺便说一句,我通过了面试,并获得了一个我现在正在考虑的角色,但我仍然不知道这里有什么更好的辅助内存调整方法。直到我们以某种方式在每个节点上跟踪只有父和祖父,然后是 O(1),这可能是 O(1) 听起来不可能的。这可能吗?
【问题讨论】:
-
(已经有Morris traversal,暂时扭曲了树。)
-
但是,如果您对父项进行额外跟踪,则辅助内存为 O(n) 并且 O(n) 比 O(h) 更差,因为 h=log(n) 并且在大多数情况下它不是退化树,即 h=n .
-
由于您必须访问每个节点来计算叔叔,因此您的起始树要么需要有父指针,要么可以修改以使用 Morris 遍历。莫里斯遍历没有辅助空间和 O(n) 时间是可能的,因为每个节点都可以在 O(1) 时间内计算其奇数孙子中有多少奇数叔叔,因为您执行中序遍历。这仍然很棘手,因为您要同时更新树和计数。
-
这是有道理的,在迭代中的每个父节点上,我只需要跟踪它的父节点(其余子节点已经可用)。有效点...
-
我在递归调用中做了一个没有数组的解决方案,方法是确保我将 parentNode 与当前节点一起传递给考虑。它似乎可以在没有任何固定数量的数组内存的情况下工作。代码也被更新和测试。但是我对代码中的堆栈有一个明显的问题,即尽管您不使用保留的数组池或 ADT 来存储递归调用,但无论如何仍然保留所有函数调用和变量,因此它消耗 O(n) 比例内存反正。我想这是最好的方法,因为没有递归就无法解决 BT 问题。
标签: algorithm binary-tree memory-efficient