【问题标题】:Finding the cheapest path down a binary tree?找到二叉树下最便宜的路径?
【发布时间】:2015-09-11 04:41:33
【问题描述】:

我正在努力寻找解决以下问题的算法:

给定一个整数的二叉树,一个分支(也就是从根开始并到达叶节点的分支)的成本由其值的总和给出。 编写一个返回最便宜分支列表的函数。

谁能推荐我完成这个练习的最简单方法?

【问题讨论】:

    标签: algorithm data-structures tree linked-list binary-tree


    【解决方案1】:

    作为提示,从树的叶子向上工作。叶子的成本只是叶子内部的值。否则,从一个节点开始的最佳路径的成本由该节点的成本加上从该节点采取的最便宜路径的成本给出。你能递归实现吗?

    希望这会有所帮助!

    【讨论】:

      【解决方案2】:

      由于树只是一个专门的图,Dijkstra 的算法在这里很有效:

      https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm

      1. 为每个节点分配一个暂定距离值:将初始节点设置为零,所有其他节点设置为无穷大。
      2. 将初始节点设置为当前节点。将所有其他节点标记为未访问。创建一个包含所有未访问节点的集合,称为未访问集。
      3. 对于当前节点,考虑其所有未访问的邻居并计算它们的暂定距离。将新计算的暂定距离与当前分配的值进行比较,并分配较小的那个。例如,如果当前节点 A 的距离为 6,连接它与邻居 B 的边的长度为 2,那么到 B(通过 A)的距离将为 6 + 2 = 8。如果 B 之前是标记的距离大于 8,然后将其更改为 8。否则,保留当前值。
      4. 当我们考虑完当前节点的所有邻居后,将当前节点标记为已访问并将其从未访问集中删除。被访问的节点将永远不会被再次检查。
      5. 如果目标节点已被标记为已访问(在规划两个特定节点之间的路线时),或者如果未访问集中节点之间的最小暂定距离为无穷大(在计划完整遍历时;发生在两个特定节点之间没有连接时)初始节点和剩余的未访问节点),然后停止。算法已完成。
      6. 否则,选择标记为最小暂定距离的未访问节点,设置为新的“当前节点”,返回步骤3。

      只需跟踪最后哪个分支的成本最低。返回具有该分支的列表。

      【讨论】:

        【解决方案3】:

        我建议先遍历树的深度。

        您将需要三个变量:

        1)current cost,代表从根节点到当前节点的值之和。

        2) cheapest path 从根到到目前为止的任何叶子(初始化为空)

        3) cheapest cost 代表最便宜路径的成本

        如果您到达一个节点,请将其节点成本添加到 current cost (1)。

        如果您到达叶子,请将其节点成本也添加到current cost。然后检查它的成本是否比cheapest cost (3) 便宜。如果是(或不存在最便宜的成本,因为它是您到达的第一片叶子)设置cheapest cost = current cost。并将cheapest path 设置为当前路径(您可以将其存储在变量本身中,或者只是从当前离开向后遍历到根节点) 然后向上一个节点检查是否有一个你还没有访问过的分支。有的话就去看看。如果没有,请转到另一个节点并检查(依此类推...)

        快捷方式: 当您到达一个节点并且它的current cost 大于cheapest cost 时,您可以跳过该节点的整个子树。

        【讨论】:

          【解决方案4】:

          您需要构建对的priority_queue(c++ stl 有这个容器):

          • 节点索引
          • 费用

          优先级是成本,递增。

          算法:

          放入priority_queue pair(root, cost_of_root)。此后,循环:

          1. 从 priority_queue 中提取对(节点、成本)
          2. 如果此节点是叶 - 返回对作为最佳叶/成本。
          3. 否则 - 将两对放入 priority_queue:(left_son, cost + left_son.cost), (right_son, cost + right_son.cost)。

          就是这样。

          【讨论】:

            【解决方案5】:

            它可以很容易地递归完成。该函数打印所有根到叶路径以及最便宜的分支。我使用 Arraylist 将所有节点从根添加到叶。每当到达叶节点时,我只需检查到目前为止的 maxSum 是否小于当前根到叶路径并更新它。

            class Node {
            
                public int info;
                public Node left;
                public Node right;
            
                public Node(int info) {
                    this(info, null, null);
                }
            
                public Node(int info, Node left, Node right) {
                    this.info = info;
                    this.left = left;
                    this.right = right;
                }
            
            }
            
            public class RootToLeaf {
            
                private static int maxSum = Integer.MAX_VALUE;
                private static ArrayList<Integer> finalList = new ArrayList<>();
            
                public static void main(String[] args) {
            
                    Node root = new Node(8);
                    root.left = new Node(4);
                    root.left.left = new Node(3);
                    root.left.right = new Node(1);
                    root.right = new Node(5);
                    root.right.right = new Node(11);
                    ArrayList<Integer> list = new ArrayList<Integer>();
                    path(root, list,0);
                    System.out.println("Cheapest list is - " + finalList.toString() +  " and minimum sum is " + maxSum);
            
                }
            
                private static void path(Node root, ArrayList<Integer> list,int s) {
            
                    if(root==null) {
                        return;
                    } else {
                        list.add(root.info);
                        s = s+root.info;
                    }
            
                    if ((root.left == null && root.right == null)) {
                        System.out.println(list);
                        if(maxSum>s) {
                            maxSum = s;
                            finalList = new ArrayList<>(list);
                        }
                        return;
                    }
            
                    path(root.left, new ArrayList<Integer>(list),s);
                    path(root.right, new ArrayList<Integer>(list),s);
            
                }
            
            }
            

            输出如下:

            [8, 4, 3]
            [8, 4, 1]
            [8, 5, 11]
            Cheapest list is - [8, 4, 1] and minimum sum is 13
            

            【讨论】:

            • 忽略打印路径成本的这种方法的时间复杂度是多少,只是找到最小总和的复杂度
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-08-03
            • 1970-01-01
            • 2018-08-10
            • 2021-07-24
            相关资源
            最近更新 更多