【问题标题】:Print all nodes that are N level above all Leaf Nodes打印所有叶子节点之上 N 级的所有节点
【发布时间】:2018-06-28 16:56:14
【问题描述】:

我需要打印所有叶子节点之上 N 级的所有节点。我尝试了以下方法,但现在我被卡住了,无法继续。请帮忙。我需要只使用 Java 7 编写代码,不需要其他版本。

例如,我有这条路径1 --> 2 --> 3 --> 4,所以在这种情况下,假设4 是我的叶节点,节点34 高1 级,节点2 比叶节点@ 高2 级987654327@ 和节点 1 比叶节点 4 高 3 级。

注意:请仅使用 Java 7。

public class NNodeBeforeLeaf {

    static Node root;
    static class Node {
        int data;
        Node left, right;
        Node(int data){
            this.data = data;
            left=right=null;
        }
    }

    public static boolean isLeaf(Node n){
        if(n.right == null && n.left == null)
            return true;
        return false;
    }

    public static void main(String[] args) {
        int level = 2;      // level N
        root = new Node(1);
        root.left = new Node(2);
        root.right = new Node(3);
        root.left.left = new Node(4);
        root.left.right = new Node(5);
        root.right.left = new Node(8);

        print(root, 0, level);
    }

    public static void print(Node n, int currLevel, int level){
        if(n == null){
            return;
        }
        if(!isLeaf(n)){
            print(n.left, currLevel + 1, level);
            print(n.right, currLevel + 1, level);
        }
        printNode(n, currLevel, level);
    }

    public static void printNode(Node n, int currLevel, int level){}

}

【问题讨论】:

  • 您能否详细说明描述,或者您可以分享一个示例输入以及输出应该是什么样子,或者如果可能的话,您可以分享问题的链接。从标题中,我无法弄清楚您到底想问什么。
  • @zenwraight 我需要的是打印每个叶节点上方“N”级的所有节点。所以我已经准备好找到每个叶节点的代码,但我被困在我需要找到一个高于我的叶节点的“N”级节点的点上。例如,我有这条路径1 --> 2 --> 3 --> 4,所以在这种情况下,假设 4 是我的叶节点,节点 3 比 4 高 1 级,节点 2 比叶节点 4 高 2 级,节点 1 比叶节点 4 高 3 级。
  • 知道了,我有个主意,很简单,我贴一下吧。
  • geeksforgeeks.org/print-nodes-distance-k-leaf-node 与叶程序的 K 距离。如果您对此感兴趣,可以根据自己的目标进行更改。
  • @PospolitaNikita 我看过那个程序,它用于打印距离叶节点 k 距离的所有节点,可以是任何方向。我只需要找到N级above叶节点的节点。

标签: java data-structures tree binary-tree binary-search-tree


【解决方案1】:

您的结构中缺少执行此操作的节点,节点知道它的子节点但不是父节点,因此您需要构建一个可以为您提供此链接的结构:这是我的建议:我构建了一个给我父节点的地图使用 buildParentMap 方法关联到一个节点这个函数已经在一次遍历中列出了所有叶子以避免在你的树上重复迭代然后我使用这个映射在每个叶子上询问的次数上升,就在这是一个 sn- p

请注意此代码有效,但如果您尝试提升该根或相同节点存在于太子中,则没有安全性(但具有相同数据的 2 个节点不会成为问题)

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;

public class NNodeBeforeLeaf {

    static Node root;

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

        Node(int data) {
            this.data = data;
            left = right = null;
        }

        @Override
        public String toString() {
            return "Node : " + data;
        }
    }

    public static boolean isLeaf(Node n) {
        if (n.right == null && n.left == null)
            return true;
        return false;
    }

    public static void main(String[] args) {
        int level = 2; // level N
        root = new Node(1);
        root.left = new Node(2);
        root.right = new Node(3);
        root.left.left = new Node(4);
        root.left.right = new Node(5);
        root.right.left = new Node(8);

        print(root, 0, level);

        int levelToUp = 1;
        HashSet<Node> result = getUpper(levelToUp, root);

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

    private static HashSet<Node> getUpper(int levelToUp, Node node) {
        HashMap<Node, Node> parenttMap = new HashMap<Node, Node>();
        LinkedList<Node> leafs = new LinkedList<Node>();
        buildParentMap(node, parenttMap, leafs);
        HashSet<Node> result = new HashSet<>();
        for (Node leaf : leafs) {
            result.add(getUpperLevel(leaf, levelToUp, parenttMap));
        }
        return result;
    }

    private static Node getUpperLevel(Node leaf, int i, HashMap<Node, Node> parenttMap) {
        Node tmp = leaf;
        while (i > 0) {
            i--;
            tmp = parenttMap.get(tmp);
        }
        return tmp;
    }

    private static void buildParentMap(Node root2, HashMap<Node, Node> hashMap, LinkedList<Node> leaf) {
        if (root2 == null) {
            return;
        } else if (isLeaf(root2)) {
            leaf.add(root2);
        } else {
            hashMap.put(root2.left, root2);
            buildParentMap(root2.left, hashMap, leaf);
            hashMap.put(root2.right, root2);
            buildParentMap(root2.right, hashMap, leaf);
        }
    }

    public static void print(Node n, int currLevel, int level) {
        if (n == null) {
            return;
        }
        printNode(n, currLevel, level);
        if (!isLeaf(n)) {
            print(n.left, currLevel + 1, level);
            print(n.right, currLevel + 1, level);
        }
    }

    public static void printNode(Node n, int currLevel, int level) {
        String output = "";
        for (int i = 0; i < currLevel; i++) {
            output += "\t";
        }
        System.out.println(output + n);
    }

}

【讨论】:

  • 即使我投了赞成票(因为这是最简单的解决方案),您也可以对树进行广度优先搜索,直到找到有问题的元素并将访问的每个元素存储在队列或堆栈中.当然,这是假设树结构是有界的。
  • 当然,所有元素(树父映射的路径,叶子)都可以通过控制器机制进行缓冲和更新^^但是我的目标是提供一个简单的算法来处理这种问题,此代码作为一些限制:如果树很深(StackOverflowError),递归也可能是一个问题我认为问题在于给出处理这个问题的逻辑,而不是一个完全优化的代码来处理他的问题
【解决方案2】:

请先阅读我的评论

由于程序中的节点仅存储它们下面的节点的数据,我真的找不到真正上树的方法':),但我可以想到这个解决方法,基本上你可以做什么也就是说,每次你需要向上 n 级时,你可以从根向下遍历到 (curLevel - n) 这是一个执行此操作的示例程序(它打印一个级别的所有节点高于当前水平,我希望这就是你的意思):

class tree{
    static class Node{
        int data;
        Node left;
        Node right;

        Node(int data){
            this.data = data;
            left = null;
            right = null;
        }
    }

    static Node root;

    public static boolean isLeaf(Node n){
        if(n.left == null && n.right == null)
            return true;
        return false;
    }

    public static void goDownTillLevel(Node n, int level){
        int l = level;
        if(n != null){
            if(level == 0) {
                System.out.println(n.data);
            }
            else{
                if(!isLeaf(n)){
                    goDownTillLevel(n.left, --level);
                    level = l; //since by the time the above function calls finished, level had been reduced to 0
                    goDownTillLevel(n.right, --level);
                }
            }
        }
    }

    public static void nLevelsAbove(Node n, int curLevel, int level){
        goDownTillLevel(root, (curLevel - level - 1));
    }

    public static void main(String args[]){
        int curLevel = 0;
        root = new Node(1);
        curLevel++;
        root.left = new Node(2);
        root.right = new Node(2);
        curLevel++;
        root.left.left = new Node(3);
        root.left.right = new Node(3);
        root.right.left = new Node(3);
        Node n = new Node(3);
        root.right.right = n;
        curLevel++;

        nLevelsAbove(n, curLevel, 1);
    }
}

虽然我想补充一点,如果向上是您关心的问题之一,请不要使用此节点结构,而是向节点添加另一个变量,即对其正上方节点的引用,这样可能是变得更容易和更短。

以上代码的输出为:

2
2

【讨论】:

    【解决方案3】:

    我认为public static boolean isLeaf(Node n)的实现是错误的,它应该只检查right是否为null否则它不是节点,也不是叶子

    要获取节点的当前级别,您可以尝试使用此代码

    int level = 0;
    while(node.right != null) {
        level++;
        node = node.right;
    }
    System.out.println("current level node: " + level);
    

    【讨论】:

      【解决方案4】:

      您的结构无法确定当前节点的高度,除非从下到上遍历。为了实现这一点,您必须先遍历叶子。

      每个递归(现在自下而上)应该返回它的高度。正如您没有说明您的树是否是完整的二叉树,一个节点可以有多个高度,具体取决于他的孩子。如果高度匹配所需的高度,则可以打印节点。

      import java.util.Collections;
      import java.util.HashSet;
      import java.util.Set;
      
      public class NNodeBeforeLeaf {
      
          static Node root;
      
          static class Node {
      
              int data;
              Node left, right;
      
              Node(int data) {
                  this.data = data;
                  left = right = null;
              }
          }
      
          public static boolean isLeaf(Node n) {
              return n.right == null && n.left == null;
          }
      
          public static void main(String[] args) {
              int level = 2;      // level N
              root = new Node(1);
              root.left = new Node(2);
              root.right = new Node(3);
              root.left.left = new Node(4);
              root.left.right = new Node(5);
              root.right.left = new Node(8);
      
              print(root, level);
          }
      
          public static void print(Node n, int level) {
              traversAndPrint(n, level);
          }
      
          private static Set<Integer> traversAndPrint(Node n, int levelToPrint) {
              if (isLeaf(n)) return Collections.singleton(0); // We are a leaf, so we have height 0
      
              final Set<Integer> childrenHeights = new HashSet<>();
      
              // are no leaf, so we have to get the heights of our children
              if (n.right != null) childrenHeights.addAll(traversAndPrint(n.right, levelToPrint));
              if (n.left != null) childrenHeights.addAll(traversAndPrint(n.left, levelToPrint));
      
              assert !childrenHeights.isEmpty();
      
              // And increase these heights
              final Set<Integer> selfHeights = new HashSet<>();
              for (Integer childrenHeigth : childrenHeights) {
                  final int selfHeight = childrenHeigth + 1;
                  selfHeights.add(selfHeight);
              }
      
              // If we have the desired height, print
              if (selfHeights.contains(levelToPrint)) printNode(n);
              return selfHeights; // return our heights
          }
      
          public static void printNode(Node n) {
              // Do whatever you want
              System.out.println(n.data);
          }
      
      }
      

      【讨论】:

        【解决方案5】:

        我找到了另一种方法。我将所有节点放在一个列表中。对于每个级别,我都会删除该列表中的叶节点。列表中的叶节点定义为 left=null 和 right=null 的节点,或者如果它们不为 null,则 left 和 right 不应该在列表中。升级后,我打印列表中的现在叶节点。

        public class NNodeBeforeLeaf {
        
        static Node root;
        
        static class Node {
            int data;
            Node left, right;
        
            Node(int data) {
                this.data = data;
                left = right = null;
            }
        }
        
        public static boolean isLeaf(Node n) {
            if ((n.right == null) && (n.left == null)) {
                return true;
            }
            return false;
        }
        
        public static void main(String[] args) {
            int level = 2; // level N
            root = new Node(1);
            root.left = new Node(2);
            root.right = new Node(3);
            root.left.left = new Node(4);
            root.left.right = new Node(5);
            root.right.left = new Node(8);
        
            printNodes(getNodesNLevelAboveLeafs(root, level));
        }
        
        public static void printNodes(List<Node> nodes) {
            for (Node n : nodes) {
                System.out.println(n.data);
            }
        }
        
        public static List<Node> getNodesNLevelAboveLeafs(Node root, int level) {
            List<Node> allNodes = listAllNodes(root);
            for (int i = 0; i < level; i++) {
                allNodes.removeAll(getLeafNodes(allNodes));
            }
            return getLeafNodes(allNodes);
        }
        
        private static List<Node> getLeafNodes(List<Node> allNodes) {
            List<Node> leafs = new ArrayList<>();
            for (Node n : allNodes) {
                if (((n.left == null) || !allNodes.contains(n.left))
                        && ((n.right == null) || !allNodes.contains(n.right))) {
                    leafs.add(n);
                }
            }
            return leafs;
        }
        
        private static List<Node> listAllNodes(Node node) {
            List<Node> nodes = new ArrayList<>();
            nodes.add(node);
            if (node.left != null) {
                nodes.addAll(listAllNodes(node.left));
            }
            if (node.right != null) {
                nodes.addAll(listAllNodes(node.right));
            }
            return nodes;
        }
        
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-02-16
          • 2017-07-30
          • 2015-05-30
          • 1970-01-01
          • 2013-03-11
          相关资源
          最近更新 更多