algorithm - 查找 k 阶斐波那契树中两个节点之间的路径

标签 algorithm tree dynamic-programming fibonacci

有一棵二叉斐波那契树,其左子树的阶数为(n-2),右子树的阶数为(n-1)。我们在构造树的时候,会按照预序的方式对节点进行标记,根从0开始,这样每个节点都有一个唯一的值。

重新标记前后的五阶斐波那契树:

fibonacci tree with order 5

enter image description here

假设我们想要找到从一个节点到另一个节点所需的步骤。为了从 5 到 7,我们输出“UUURL”,其中 U 表示向上,L 表示左 child ,R 表示右 child 。

我认为通过构造第二棵树,然后找到两个节点的最低公共(public)祖先,计算此输出非常简单。与以下问题的解决方案基本相同:https://leetcode.com/problems/step-by-step-directions-from-a-binary-tree-node-to-another/

还有其他使用动态规划的解决方案吗?我觉得应该有一种方法可以利用斐波那契特性,而不是处理一棵常规树并进行完全遍历。

编辑:输入是斐波那契树的顺序、源数和目标数。对于给定的示例,输入为

订单:5
来源:5
目的地:7

最佳答案

下面的 Python 解决方案将问题分解为三部分。

  1. 树的数据类型,具有将深度优先索引转换为路径的方法(类 Leaf 和 Branch)。这是扩充树以通过索引访问的经典方法。

  2. 使用上述数据类型构建请求订单的斐波那契树。由于共享,这是高效的。

  3. 将两条下行路径转换为一条上行路径,然后是一条下行路径。

为了清晰起见,我以牺牲效率为代价进行了优化,但这里的想法给出了一个在 O(order) 时间内运行的算法。

class Leaf:
    def __len__(self):
        return 1

    def path(self, dest):
        assert 0 <= dest < len(self)
        return ""


class Branch:
    def __init__(self, left, right):
        self._left = left
        self._right = right
        self._len = 1 + len(left) + len(right)

    def __len__(self):
        return self._len

    def path(self, dest):
        assert 0 <= dest < len(self)
        if dest < 1:
            return ""
        dest -= 1
        if dest < len(self._left):
            return "L" + self._left.path(dest)
        dest -= len(self._left)
        return "R" + self._right.path(dest)


def fib_tree(order):
    fib_trees = [Leaf(), Leaf()]
    while len(fib_trees) <= order:
        fib_trees.append(Branch(fib_trees[-2], fib_trees[-1]))
    return fib_trees[order]


def left_divide(source_path, dest_path):
    n = min(len(source_path), len(dest_path))
    i = min((j for j in range(n) if source_path[j] != dest_path[j]), default=n)
    return "U" * (len(source_path) - i) + dest_path[i:]


def fib_path(order, source, dest):
    tree = fib_tree(order)
    return left_divide(tree.path(source), tree.path(dest))


print(fib_path(5, 5, 7))
# UUURL

关于algorithm - 查找 k 阶斐波那契树中两个节点之间的路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76142856/

相关文章:

c++ - 如何判断一个点是否在矩形内?

algorithm - 创建一堆盒子的最佳解决方案

javascript - Target Sum 没有输出正确的值

Javascript:涉及I/O的有向树的DFS遍历

algorithm - 给定一台重量最大的电梯和重量为 x_i 的 n 个人,找出所需的最少乘车次数

algorithm - 惰性传播线段树实现难点

r - 向树添加信息 - Rpart

c++ - 使用动态规划找到最大数量

algorithm - 设施位置的动态规划算法

java - 如何在java中导出霍夫曼解码/编码项目的树数据结构?