打印距给定节点距离k的所有节点

时间:2016-07-04 17:58:39

标签: algorithm tree

enter image description here 树没有任何父指针。 如果这是图并且目标是10并且k是2,那么输出应该是150,160,8,14。 http://www.geeksforgeeks.org/print-nodes-distance-k-given-node-binary-tree/有一个解决方案,虽然我无法理解它。

所以我根据第一个答案从树中构建了一个无向图。 我认为printN的复杂性不是O(n)。任何人都可以检查一下。 谢谢!

public class Nth {
    private int targetV;

    private class Node {
        private int data;
        private Node left, right;

        public Node() {
        }

        public Node(int data) {
            this.data = data;
        }
    }

    private class GraphNode {
        private HashMap<Integer, ArrayList<Integer>> edgeMap;

        GraphNode() {
            edgeMap = new HashMap<>();
        }

        private void addEdge(int v, int w) {
            if (edgeMap.containsKey(v)) {
                if (!edgeMap.get(v).contains(w))
                    edgeMap.get(v).add(w);
            } else {
                edgeMap.put(v, new ArrayList<>());
                edgeMap.get(v).add(w);
            }
        }
    }

    public static void main(String[] args) {
        new Nth().job1();
    }

    private void job1() {
        Node root = new Node(20);
        root.left = new Node(8);
        root.left.left = new Node(4);
        root.left.right = new Node(12);
        root.left.right.left = new Node(10);
        root.left.right.left.left = new Node(50);
        root.left.right.left.left.left = new Node(150);
        root.left.right.left.left.left.left = new Node(1250);
        root.left.right.left.left.left.right = new Node(12512);
        root.left.right.left.left.right = new Node(160);
        root.left.right.left.right = new Node(60);
        root.left.right.right = new Node(14);
        root.right = new Node(22);
        GraphNode graphNode = new GraphNode();
        generateGraph(null, null, root, graphNode, 10);
        check(graphNode);
        // printN(graphNode, 2);
    }

private void printN(GraphNode graphNode, int k) {
    Set<Integer> items = new HashSet<>();
    Queue<Integer> queue = new ArrayDeque<>();
    queue.add(targetV);
    HashMap<Integer, Boolean> hashMap = new HashMap<>();
    hashMap.put(targetV, true);
    for (int e = 0; e < k; e++) {
        items.clear();
        Queue<Integer> back = new ArrayDeque<>();
        back.addAll(queue);
        int xq = back.size();
        queue.clear();
        for (int i = 0; i < xq; i++) {
            int polled = back.poll();
            ArrayList<Integer> list = graphNode.edgeMap.get(polled);
            list.forEach((x) -> {
                if (!hashMap.containsKey(x)) {
                    queue.add(x);
                    hashMap.put(x, true);
                }
            });
        }
        items.addAll(queue);
    }

    System.out.println(Arrays.toString(items.toArray()));
}

    private void check(GraphNode graphNode) {
        for (Map.Entry<Integer, ArrayList<Integer>> pop : graphNode.edgeMap.entrySet()) {
            System.out.println(pop.getKey() + "\t\t\t" + Arrays.toString(pop.getValue().toArray()));
        }
    }

    private void generateGraph(Node parent, Node root, Node child, GraphNode graphNode, int target) {
        if (child == null && root != null && parent != null)
            graphNode.addEdge(root.data, parent.data);
        if (child == null) return;
        if (root != null) graphNode.addEdge(root.data, child.data);
        if (parent != null && root != null) graphNode.addEdge(root.data, parent.data);
        if (child.data == target) targetV = child.data;
        generateGraph(root, child, child.left, graphNode, target);
        generateGraph(root, child, child.right, graphNode, target);
    }

}

我的检查乐趣打印:

        160         [50]
        1250        [150]
        1251        [150]
        4           [8]
        8           [4, 20, 12]
        10          [50, 12, 60]
        12          [10, 8, 14]
        14          [12]
        50          [150, 10, 160]
        20          [8, 22]
        150         [1250, 50, 1251]
        22          [20]
        60          [10]

2 个答案:

答案 0 :(得分:2)

不要把它看成一棵树。将其视为通常连接的双向图并从选定的顶点开始BFS。在BFS搜索的第k步/深度跟踪所有唯一顶点。

答案 1 :(得分:1)

您目前正在尝试理解的链接中给出的算法分为两部分:

  1. 查找远离目标节点的k目标节点的所有子项
  2. 查找远离目标节点的k的其他节点(即非子节点)
  3. 我相信你明白如何解决1,这可以通过目标节点的BFS轻松完成。

    然而,您对如何解决2的理解是不正确的。

    从树的根开始,当我们遍历树以找到目标节点时,跟踪目标节点的所有祖先(包括根)。

    然后:

    • 目标节点的父节点距离目标1。因此,从父节点执行BFS以从父节点中查找k-1的所有节点。
    • 目标节点的祖父节点距离目标2。因此,从祖父节点执行BFS,以从祖父节点中查找k-2的所有节点。
    • 目标节点的祖父节点距离目标3。因此,从曾祖父节点执行BFS,以查找来自曾祖父节点的k-3的所有节点。
    • 等。一直到树根,如果需要,即k足够大,以便需要这样做。

    从祖先执行BFS时,您需要注意不要遍历到目标节点。

    最后,我想补充一点,更简单的算法是:

    1. 完全遍历树一次以创建父指针(为什么你不会有父指针?要保存每个指针所需的32/64位?)
    2. 从目标节点执行BFS遍历父指针和子指针。