【问题标题】:print all root to leaf paths in a binary tree打印二叉树中的所有根到叶路径
【发布时间】:2013-02-18 12:54:42
【问题描述】:

我正在尝试使用 java 打印二叉树中的所有根到叶路径。

public void printAllRootToLeafPaths(Node node,ArrayList path) 
{
    if(node==null)
    {
        return;
    }
    path.add(node.data);

    if(node.left==null && node.right==null)
    {
        System.out.println(path);
        return;
    }
    else
    {
        printAllRootToLeafPaths(node.left,path);
        printAllRootToLeafPaths(node.right,path);
    }      
}

在主方法中:

 bst.printAllRootToLeafPaths(root, new ArrayList());

但它给出了错误的输出。

给定树:

   5
  / \
 /   \
1     8
 \    /\
  \  /  \
  3  6   9

预期输出:

[5, 1, 3]

[5, 8, 6]

[5, 8, 9]

但产生的输出:

[5, 1, 3]

[5, 1, 3, 8, 6]

[5, 1, 3, 8, 6, 9]

有人能解决吗...

【问题讨论】:

  • 我们需要更多信息来帮助您。 "但它给出了错误的输出。" --> 你的输入是什么?您期望什么输出(以及为什么)以及实际输出是什么?
  • 感谢您的建议。但是其他人理解我的问题并给出了所需的答案......
  • @jlordo:输入显然是一棵给定根节点的树。预期的输出是:从根到叶的所有路径。(问题中明确提到)。错误的输出意味着:预期的输出没有到来......
  • 这里是Stack Overflow question checklist,关于如何写一个好问题。一个要点:如果您的程序产生的结果与您的预期不同,您是否说明了您的预期、预期的原因以及实际结果?
  • @lok​​nath 人们猜对了这一事实并不意味着您的问题已经尽可能/应该清楚。请务必查看 jlordo 发布的清单。

标签: java tree binary-tree


【解决方案1】:

调用递归方法:

printAllRootToLeafPaths(node.left, new ArrayList(path));
printAllRootToLeafPaths(node.right, new ArrayList(path));

当您传递path(而不是new ArrayList(path))时发生的情况是您在所有方法调用中使用单个对象,这意味着,当您返回原始调用者时,对象不在同一个保持原样。

您只需要创建一个新对象并将其初始化为原始值。这样原始对象就不会被修改。

【讨论】:

  • 这确实有效,但我不知道“new ArrayList(path)”在做什么。它是完全创建一个新的路径列表,还是覆盖以前的路径。当我们说新的时候,是不是意味着我们重置了路径?我刚接触编程,感谢您的帮助,谢谢。
  • 如果它是无参数的(即只是new ArrayList()),那么是的,它将是一个新的、空的列表。但是,使用参数path,它会创建一个新列表,然后从path 列表中复制值。这样,原始列表的内容,即path,不会被覆盖。您只使用原始列表的值,而不是列表本身。 :)
  • 如果我没记错的话,这是因为 ArrayList 是可变的。
【解决方案2】:
public void PrintAllPossiblePath(Node node,List<Node> nodelist)
{
    if(node != null)
    {
            nodelist.add(node);
            if(node.left != null)
            {
                PrintAllPossiblePath(node.left,nodelist);
            }
            if(node.right != null)
            {
                PrintAllPossiblePath(node.right,nodelist);
            }
            else if(node.left == null && node.right == null)
            {

            for(int i=0;i<nodelist.size();i++)
            {
                System.out.print(nodelist.get(i)._Value);
            }
            System.out.println();
            }
            nodelist.remove(node);
    }
}

nodelist.remove(node) 是关键,它会在打印相应的路径后删除元素

【讨论】:

  • 运行您的解决方案有效。 nodelist 和 node 一样,是一个局部变量。假设一个节点有 2 个子节点,它处理了左子树。返回节点访问右孩子时,为什么nodelist有来自左子树的节点?由于 nodelist 是本地的,它不应该记住该堆栈帧中的列表,它不知道左子树吗?同样的原因,节点不会是左子树中的值,因为它被弹出了。
  • @Jeevan 当我写 List L = new List() 时,它给出了一个错误,并说删除类型参数。你知道为什么吗? (java.awt.List 被导入)
【解决方案3】:

您正在递归地传递您的列表,但这是一个可变对象,因此所有调用都会修改它(通过调用List.add)并破坏您的结果。尝试将 path 参数克隆/复制到所有递归调用中,以便为每个分支 (harhar) 提供自己的上下文。

【讨论】:

    【解决方案4】:

    你也可以这样做。 这是我的 Java 代码。

    public void printPaths(Node r,ArrayList arr)
    {
        if(r==null)
        {
            return;
        }
        arr.add(r.data);
        if(r.left==null && r.right==null)
        {
            printlnArray(arr);
        }
        else
        {
            printPaths(r.left,arr);
            printPaths(r.right,arr);
        }
    
         arr.remove(arr.size()-1);
    }
    

    【讨论】:

      【解决方案5】:

      这是正确的实现

      public static <T extends Comparable<? super T>> List<List<T>> printAllPaths(BinaryTreeNode<T> node) {
          List <List<T>> paths = new ArrayList<List<T>>();
          doPrintAllPaths(node, paths, new ArrayList<T>());
          return paths;
      }
      
      private static <T extends Comparable<? super T>> void doPrintAllPaths(BinaryTreeNode<T> node, List<List<T>> allPaths, List<T> path) {
          if (node == null) {
              return ;
          }
          path.add(node.getData());
          if (node.isLeafNode()) {
              allPaths.add(new ArrayList<T>(path));   
      
          } else {
              doPrintAllPaths(node.getLeft(), allPaths, path);
              doPrintAllPaths(node.getRight(), allPaths, path);
          }
          path.remove(node.getData());
      }
      

      这是测试用例

      @Test
      public void printAllPaths() {
          BinaryTreeNode<Integer> bt = BinaryTreeUtil.<Integer>fromInAndPostOrder(new Integer[]{4,2,5,6,1,7,3}, new Integer[]{4,6,5,2,7,3,1});
          List <List<Integer>> paths = BinaryTreeUtil.printAllPaths(bt);
      
          assertThat(paths.get(0).toArray(new Integer[0]), equalTo(new Integer[]{1, 2, 4}));
          assertThat(paths.get(1).toArray(new Integer[0]), equalTo(new Integer[]{1, 2, 5, 6}));
          assertThat(paths.get(2).toArray(new Integer[0]), equalTo(new Integer[]{1, 3, 7}));
      
          for (List<Integer> list : paths) {          
              for (Integer integer : list) {
                  System.out.print(String.format(" %d", integer));
              }
              System.out.println();
          }
      }
      

      这是输出

      1 2 4
      
      1 2 5 6
      
      1 3 7
      

      【讨论】:

        【解决方案6】:

        这是我的解决方案:一旦我们遍历左侧或右侧路径,只需删除最后一个元素。

        代码:

        public static void printPath(TreeNode root, ArrayList list) {
        
            if(root==null)
                return;
        
            list.add(root.data);
        
            if(root.left==null && root.right==null) {
                System.out.println(list);
                return;
            }
            else {
                printPath(root.left,list);
                list.remove(list.size()-1);
        
                printPath(root.right,list);
                list.remove(list.size()-1);
        
            }
        }
        

        【讨论】:

          【解决方案7】:
          /* Given a binary tree, print out all of its root-to-leaf
             paths, one per line. Uses a recursive helper to do the work.*/
          void printPaths(Node node) 
          {
              int path[] = new int[1000];
              printPathsRecur(node, path, 0);
          }
          
          /* Recursive helper function -- given a node, and an array containing
             the path from the root node up to but not including this node,
             print out all the root-leaf paths. */
          void printPathsRecur(Node node, int path[], int pathLen) 
          {
              if (node == null)
                  return;
          
              /* append this node to the path array */
              path[pathLen] = node.data;
              pathLen++;
          
              /* it's a leaf, so print the path that led to here */
              if (node.left == null && node.right == null)
                  printArray(path, pathLen);
              else
                  { 
                  /* otherwise try both subtrees */
                  printPathsRecur(node.left, path, pathLen);
                  printPathsRecur(node.right, path, pathLen);
              }
          }
          
          /* Utility that prints out an array on a line */
          void printArray(int ints[], int len) 
          {
              int i;
              for (i = 0; i < len; i++) 
                  System.out.print(ints[i] + " ");
              System.out.println("");
          }
          

          【讨论】:

            【解决方案8】:

            我用ArrayList 尝试了这个问题,我的程序打印了类似的路径。

            所以我通过维护内部count 修改了我的逻辑以正常工作,这就是我的做法。

            private void printPaths(BinaryNode node, List<Integer> paths, int endIndex) {
                    if (node == null)
                        return;
                    paths.add(endIndex, node.data);
                    endIndex++;
                    if (node.left == null && node.right == null) {
                        //found the leaf node, print this path
                        printPathList(paths, endIndex);
                    } else {
                        printPaths(node.left, paths, endIndex);
                        printPaths(node.right, paths, endIndex);
                    }
                }
            
            public void printPaths() {
                List<Integer> paths = new ArrayList<>();
                printPaths(root, paths, 0);
            }
            

            【讨论】:

              【解决方案9】:

              我们可以使用递归来实现它。正确的数据结构使其简洁高效。

              List<LinkedList<Tree>> printPath(Tree root){
              
                  if(root==null)return null;
              
                  List<LinkedList<Tree>> leftPath= printPath(root.left);
                  List<LinkedList<Tree>> rightPath= printPath(root.right);
              
                  for(LinkedList<Tree> t: leftPath){
                       t.addFirst(root);
                  }
                  for(LinkedList<Tree> t: rightPath){
                       t.addFirst(root);
                  }
              
              
               leftPath.addAll(rightPath);
              
               return leftPath;
              
              
              }
              

              【讨论】:

                【解决方案10】:

                您可以执行以下操作,

                public static void printTreePaths(Node<Integer> node) {
                    int treeHeight = treeHeight(node);
                    int[] path = new int[treeHeight];
                    printTreePathsRec(node, path, 0);
                
                }
                
                private static void printTreePathsRec(Node<Integer> node, int[] path, int pathSize) {
                    if (node == null) {
                        return;
                    }
                
                    path[pathSize++] = node.data;
                
                    if (node.left == null & node.right == null) {
                        for (int j = 0; j < pathSize; j++ ) {
                            System.out.print(path[j] + " ");
                        }
                        System.out.println();
                    }
                
                     printTreePathsRec(node.left, path, pathSize);
                     printTreePathsRec(node.right, path, pathSize);
                }
                

                public static int treeHeight(Node<Integer> root) {
                    if (root == null) {
                        return 0;
                    }
                
                    if (root.left != null) {
                        treeHeight(root.left);
                    }
                
                    if (root.right != null) {
                        treeHeight(root.right);
                    }
                
                    return Math.max(treeHeight(root.left), treeHeight(root.right)) + 1;
                
                }
                

                【讨论】:

                  【解决方案11】:

                  这是我将所有路径值存储在 List 中然后打印列表的解决方案

                  基本上是什么代码递归调用rootToLeafPaths 方法并将字符串传递给以逗号(“,”)分隔的值。递归函数的基本条件是当我们到达叶节点时(两个孩子都是空的)。那时,我们只是从字符串中提取 int 值并将其存储在 List 中

                  class Solution {
                      public void printBTfromRootToLeaf (TreeNode root) {
                          if(root == null) return 0;
                          if (root.left == null & root.right == null) return 1;
                          List<List<Integer>> res = new ArrayList();
                          rootToLeafPaths(root, res, "");
                          System.out.println(res);
                      }
                  private void rootToLeafPaths(TreeNode root, List<List<Integer>> res, String curr) {
                          if (root.left == null && root.right == null) {
                              String[] vals = curr.split(",");
                              List<Integer> temp = new ArrayList<>();
                              for (String val : vals) temp.add(Integer.parseInt(val));
                              temp.add(root.val);
                              res.add(new ArrayList<>(temp));
                          }
                          if (root.left != null) rootToLeafPaths(root.left, res, curr + root.val + ",");
                          if (root.right != null) rootToLeafPaths(root.right, res, curr + root.val + ",");
                      }
                  }
                  

                  【讨论】:

                  • 虽然此代码可以解决问题,including an explanation 说明如何以及为什么解决问题将真正有助于提高您的帖子质量,并可能导致更多的赞成票。请记住,您正在为将来的读者回答问题,而不仅仅是现在提问的人。请edit您的答案以添加解释并说明适用的限制和假设。 From Review
                  【解决方案12】:

                  它是用JS编写的,但你可以得到逻辑。

                  function dive(t, res, arr) {
                          if(t.value != null && t.value != undefined) {
                              res = res ? `${res}->${t.value}`: `${t.value}`;
                          }
                          if(t.left) {
                              dive(t.left, res, arr );
                          } 
                          if(t.right) {
                              dive(t.right, res, arr );
                          } 
                          if(!t.left && !t.right) {
                              console.log(res)
                              arr.push(res);
                              return;
                          }
                  }
                  
                  function getPaths(t) {
                      let arr = [];
                      if(!t.left && !t.right) {
                          t.value != null && t.value != undefined && arr.push(`${t.value}`);
                          console.log(arr)
                          return arr;
                      }
                      dive(t, null, arr);
                      console.log(arr)
                  }
                  
                  
                  //INPUT
                  const x = {
                      value: 5,
                      left: {
                          value: 4,
                          left: {
                              value: 3,
                              left: {
                                  value: 2,
                                  left: {
                                      value: 1,
                                      left: {
                                          value: 0
                                      },
                                      right: {
                                          value: 1.5
                                      }
                                  },
                                  right: {
                                      value: 2.5
                                  }
                              },
                              right: {
                                  value: 3.5
                              }
                          },
                          right: {
                              value: 4.5,
                              right: {
                                  value: 4.8
                              }
                          }
                      },
                      right: {
                          value: 8,
                          left: {
                              value: 7
                          }
                      }
                  }
                  
                  getPaths(x);
                  
                  //OUTPUT
                  
                  [ '5->4->3->2->1->0',
                    '5->4->3->2->1->1.5',
                    '5->4->3->2->2.5',
                    '5->4->3->3.5',
                    '5->4->4.5->4.8',
                    '5->8->7' ]
                  
                  

                  【讨论】:

                  • 最好是写cmets和解释代码的作用,而不是简单地转储它。
                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2016-08-29
                  • 2021-09-29
                  • 1970-01-01
                  • 1970-01-01
                  • 2018-03-04
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多