在二叉树中找到最便宜的路径?

时间:2015-06-24 19:49:36

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

我正在努力为以下问题找到算法:

  

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

Exercise

有人能推荐我完成这项练习的最简单方法吗?

5 个答案:

答案 0 :(得分:5)

可以很容易地递归完成。该函数打印所有根到叶子路径以及最便宜的分支。我使用Arraylist将所有节点从root添加到leaf。每当到达叶子节点时,我只检查到目前为止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

答案 1 :(得分:3)

作为暗示,从树的叶子向上工作。叶子的成本就是叶子里面的价值。否则,从节点开始的最佳路径的成本由该节点的成本加上从那里获得的最便宜路径的成本给出。你能递归地实现这个吗?

希望这有帮助!

答案 2 :(得分:1)

我建议首先遍历树深度。

您需要三个变量:

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时,您可以跳过该节点的整个子树。

答案 3 :(得分:1)

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

  • 节点索引
  • 成本

优先级是成本,升序。

算法:

加入priority_queue对(root,cost_of_root)。此后,循环:

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

答案 4 :(得分:0)

由于树只是一个专门的图形,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. 否则,选择标记有最小暂定距离的未访问节点,将其设置为新的&#34;当前节点&#34;,然后返回步骤3.
  7. 只需跟踪最终成本最低的分支。返回包含该分支的列表。