【问题标题】:Finding max depth of binary tree without recursion无需递归即可找到二叉树的最大深度
【发布时间】:2013-11-22 01:42:03
【问题描述】:

找到二叉树最大深度的递归机制非常简单,但是我们如何在没有递归的情况下有效地做到这一点,因为我有大树,我宁愿避免这种递归。

//Recursive mechanism which I want to replace with non-recursive
private static int maxDepth(Node node) {
if (node == null) return 0;
    return 1 + Math.max(maxDepth(node.left), maxDepth(node.right)); 
}

PS:我正在用 Java 寻找答案。

【问题讨论】:

    标签: java algorithm recursion binary-tree


    【解决方案1】:

    如果你能在每个节点保持左右值,就可以做到。

    http://leetcode.com/2010/04/maximum-height-of-binary-tree.html.

    可能重复: Retrieving a Binary-Tree node's depth non-recursively

    【讨论】:

      【解决方案2】:

      您描述的递归方法本质上是二叉树上的 DFS。如果您愿意,可以通过存储显式节点堆栈并跟踪遇到的最大深度来迭代地实现这一点。

      希望这会有所帮助!

      【讨论】:

      • 你能提供任何样品吗?这是有效的方法吗?因为我不想增加空间复杂度。
      • @Hemant- 迭代和递归 DFS 具有相同的时间和空间复杂性,尽管递归版本通常使用堆栈空间,而迭代版本使用堆空间。搜索“iterative DFS”寻找一些好的伪代码作为起点。
      【解决方案3】:

      我编写了以下逻辑来查找不涉及递归且不增加空间复杂度的最大和最小深度。

      // Find the maximum depth in the tree without using recursion
      private static int maxDepthNoRecursion(TreeNode root) {
          return Math.max(maxDepthNoRecursion(root, true), maxDepthNoRecursion(root, false)); 
      }
      
      // Find the minimum depth in the tree without using recursion
      private static int minDepthNoRecursion(TreeNode root) {
          return Math.min(maxDepthNoRecursion(root, true), maxDepthNoRecursion(root, false)); 
      }
      
      private static int maxDepthNoRecursion(TreeNode root, boolean left) {
          Stack<TreeNode> stack = new Stack<>();
          stack.add(root);
          int depth = 0;
          while (!stack.isEmpty()) {
              TreeNode node = stack.pop();
              if (left && node.left != null) stack.add(node.left);
              // Add the right node only if the left node is empty to find max depth
              if (left && node.left == null && node.right != null) stack.add(node.right); 
              if (!left && node.right != null) stack.add(node.right);
              // Add the left node only if the right node is empty to find max depth
              if (!left && node.right == null && node.left != null) stack.add(node.left);
              depth++;
          }
          return depth;
      }
      

      【讨论】:

      • 您实际上不需要跟踪访问过的节点,因为在树中,从根到任何其他节点只有一条路径。
      • @chill - 不跟踪访问过的节点会导致递归,即使树没有任何循环引用。
      • 哦,你的意思是你的特定算法?好的。有关具有预期 O(log n) 额外空间复杂度的变体,请参阅我的答案。
      • 该算法似乎不适用于树的某些结构。它为下面的树返回最大深度 3(预期为 4)。节点1.左=节点2;节点1.right=节点3;节点2.左=节点4;节点2.right=节点5;节点3.左=节点6;节点3.right=节点7;节点5.right=节点8; node6.left=node9;
      • 完全错误的算法,只有当最大深度在树的左节点左侧或树的根节点的右侧时才会考虑。试试这个,它会失败 tree2.Insert(30);树2.插入(10);树2.插入(50);树2.插入(5);树2.插入(11);树2.插入(12);树2.插入(13); tree2.Insert(14);
      【解决方案4】:

      此变体使用两个堆栈,一个用于探索其他节点 (wq),另一个始终包含来自根的当前路径 (path)。当我们在两个堆栈的顶部看到相同的节点时,这意味着我们已经探索了它下面的所有内容并且可以弹出它。这也是更新树深度的时候了。当然,在随机树或平衡树上,额外空间应该是 O(log n),在最坏的情况下是 O(n)。

      static int maxDepth (Node r) {
          int depth = 0;
          Stack<Node> wq = new Stack<>();
          Stack<Node> path = new Stack<>();
      
          wq.push (r);
          while (!wq.empty()) {
              r = wq.peek();
              if (!path.empty() && r == path.peek()) {
                  if (path.size() > depth)
                      depth = path.size();
                  path.pop();
                  wq.pop();
              } else {
                  path.push(r);
                  if (r.right != null)
                      wq.push(r.right);
                  if (r.left != null)
                      wq.push(r.left);
              }
          }
      
          return depth;
      }
      

      (无耻插件:几周前我有使用双栈进行非递归遍历的想法,请在此处检查 C++ 代码 http://momchil-velikov.blogspot.com/2013/10/non-recursive-tree-traversal.html 并不是我声称我是第一个发明它的人 :)

      【讨论】:

      • 谢谢 - 我已经接受了你的回答,因为它没有保留经过的节点列表,这增加了空间复杂性。
      • 一个实现说明:在 Java 中最好使用 ArrayDeque 而不是 StackStack 类是不必要的同步。
      【解决方案5】:

      另一种方法是使用Level order traversal,其中树高等于树的层数。 (只能用来计算树的最小高度。)

      public int maxDepth(TreeNode root) {
          if (root == null) return 0;
          LinkedList<TreeNode> arr = new LinkedList<TreeNode>(); // queue for current level
          LinkedList<TreeNode> tmp = new LinkedList<TreeNode>(); // queue for next level
          arr.add(root);
          int res = 0; // result
          TreeNode node; // tmp node 
          while (true) {
              while (!arr.isEmpty()) {
                  node = arr.poll();
                  if (node.left != null) tmp.add(node.left);
                  if (node.right != null) tmp.add(node.right);
              }
              res++;
              if (tmp.isEmpty()) break;
              arr = tmp;
              tmp = new LinkedList<TreeNode>();
          }
          return res;
      }
      

      【讨论】:

        【解决方案6】:

        使用Array存储一层节点,每次查找新层。深度加一。

        public int maxDepth2(TreeNode root){
                if(root == null){
                    return 0;
                }
        
                int depth = 0;
        
                ArrayList<TreeNode> oneLayer = new ArrayList<TreeNode>();
                oneLayer.add(root);
        
                while(!oneLayer.isEmpty()){
                    ArrayList<TreeNode> newLayer = new ArrayList<TreeNode>();
                    for(TreeNode node:oneLayer){
                        if(node.right!=null){
                            newLayer.add(node.right);
                        }
                        if(node.left!=null){
                            newLayer.add(node.left);
                        }
                    }
                    oneLayer = newLayer;
                    depth++;
                }
        
                return depth;
            }
        

        【讨论】:

          【解决方案7】:

          这是一个 BFS 解决方案:

          private class NodeHeight
          {
              public Node node;
              public int height;
          
              public NodeHeight(Node n, int height)
              {
                  node = n;
                  this.height = height;
              }
          }
          
          public int GetHeightBfs(Node root)
          {
              if(root == null)
                  return 0;
              else
                  return GetHeightBfs(new NodeHeight(root, 1))
          }
          
          private int GetHeightBfs(NodeHeight root)
          {   
              int maxHeight = int.Min;
              int minHeight = int.Max;
              var q = new Queue<Node>();
              q.Enqueue(root);
              while(q.length > 0)
              {       
                  var nodeHeight = q.Dequeue();
                  var node = nodeHeight.node;
                  int height = nodeHeight.height;
                  if(node.left == null && node.right == null)
                  {
                      maxHeight = Math.max(maxHeight, height);
                      minHeight = Math.min(minHeight, height);
                  }
          
                  if(node.left != null)
                      q.Enqueue(new NodeHeight(node.left, height + 1);
          
                  if(node.right != null)
                      q.Enqueue(new NodeHeight(node.right, height + 1);
              }
          
              return maxHeight;
          }   
          

          请注意,您也可以返回 minHeight。 要使其成为 DFS,只需将 Queue 替换为 Stack。

          【讨论】:

            猜你喜欢
            • 2019-09-08
            • 1970-01-01
            • 2016-01-24
            • 1970-01-01
            • 2015-04-08
            • 2015-02-12
            • 1970-01-01
            • 2016-06-14
            • 1970-01-01
            相关资源
            最近更新 更多