【问题标题】:Iterative Solution to finding if a tree is balanced查找树是否平衡的迭代解决方案
【发布时间】:2016-03-28 03:08:06
【问题描述】:

所以有人发布了他们的解决方案,但我发现它似乎不起作用,我将其发布在那里,但我想让其他人更容易访问它。

问题在“Cracking the Code Interview”中,这是第一个树问题,请随时提出其他建议(或证明我错了!)

【问题讨论】:

    标签: java algorithm iteration binary-tree


    【解决方案1】:

    这里的关键是很难用一个堆栈跟踪最终路径及其高度。

    我最终做的是将左右孩子的高度都推入堆栈,检查它们是否在彼此之间,将最大值加一,然后在左右弹出后将其推入堆栈.

    我已经评论了,所以我希望它足够清楚

     /* Returns true if binary tree with root as root is height-balanced */
            boolean isBalanced(Node root) {
                if(root == null) return false;
    
                Deque<Integer> heights = new LinkedList<>();
                Deque<Node> trail = new LinkedList<>();
                trail.push(root);
    
                Node prev = root; //set to root not null to not confuse when root is misisng children
    
                while(!trail.isEmpty()) {
                    Node curr = trail.peek(); //get the next node to process, peek because we need to maintain trail until we return
    
                    //if we just returned from left child
                    if (curr.left == prev) {
                        if(curr.right != null) trail.push(curr.right); //if we can go right go
                        else {
                            heights.push(-1); //otherwise right height is -1 does not exist and combine heights
                            if(!combineHeights(heights)) return false;
                            trail.pop(); //back to parent
                        }
                    }
                    //if we just returned from right child
                    else if (curr.right == prev) {
                        if(!combineHeights(heights)) return false;
                        trail.pop(); //up to parent
                    }
                    //this came from a parent, first thing is to visit the left child, or right if no left
                    else {
                        if(curr.left != null) trail.push(curr.left);
                        else {
                            if (curr.right != null) {
                                heights.push(-1); //no left so when we combine this node left is 0
                                trail.push(curr.right); //since we never go left above logic does not go right, so we must here
                            }
                            else { //no children set height to 1
                                heights.push(0);
                                trail.pop(); //back to parent
                            }
                        }
                    }
    
                    prev = curr;
                }
    
                return true;
            }
    
            //pop both previous heights and make sure they are balanced, if not return false, if so return true and push the greater plus 1
            private boolean combineHeights(Deque<Integer> heights) {
                int rightHeight = heights.pop();
                int leftHeight = heights.pop();
    
                if(Math.abs(leftHeight - rightHeight) > 1) return false;
                else heights.push(Math.max(leftHeight, rightHeight) + 1);
                return true;
            }
    

    【讨论】:

      【解决方案2】:

      书中的原始问题没有提到树是二元的。我碰巧解决了同样的问题,但用 Python 编码。因此,这是我在 python 中针对一般树(节点的子节点存储在列表中)的问题的迭代解决方案。

      def is_balanced_nonrecursive(self):
          stack = [self.root]
          levels = [0]
          current_min = sys.maxint
          current_max = 0
          current_level = 0
          while len(stack) > 0:
              n = stack.pop()
              current_level = levels.pop()
              for c in n.children:
                  stack.append(c)
                  levels.append(current_level + 1)
              if len(n.children) == 0:
                  if current_level < current_min:
                      current_min = current_level
                  if current_level > current_max:
                      current_max = current_level
          return current_max - current_min < 2
      

      这基本上是树的深度优先遍历。我们为级别保留一个单独的堆栈(列表levels)。如果我们看到任何叶节点,我们会相应地更新当前最小和当前最大级别。该算法遍历整棵树,最后如果最大和最小级别相差超过 1,则树不平衡。

      有许多优化可能,例如检查循环内的 min 和 max 的差是否大于 1,如果是,则立即返回 False

      【讨论】:

        【解决方案3】:

        在这方面有一些代码重复,但至少它不会像递归的那样让我头疼:

        public boolean isBalanced() {
            Queue<TreeNode> queue = new LinkedList<TreeNode>();
            int leftLevel = 0;
            int rightLevel = 0;
            if(this == null) return false;
            if(this.left != null)queue.offer(this.left);
        
            while(!queue.isEmpty()) {
                int size = queue.size();
                for(int i=0; i < size; i++) {
                    if(queue.peek().left != null) queue.offer(queue.peek().left);
                    if(queue.peek().right != null) queue.offer(queue.peek().right);
                    queue.poll();
                }
                leftLevel++;
            }
        
            if(this.right != null) queue.offer(this.right);
        
            while(!queue.isEmpty()) {
                int size = queue.size();
                for(int i=0; i < size; i++) {
                    if(queue.peek().left != null) queue.offer(queue.peek().left);
                    if(queue.peek().right != null) queue.offer(queue.peek().right);
                    queue.poll();
                }
                rightLevel++;
            }
            return Math.abs(leftLevel - rightLevel) < 2;
        }
        

        【讨论】:

          猜你喜欢
          • 2020-07-21
          • 2019-03-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-07-22
          • 1970-01-01
          • 2016-03-19
          • 2021-04-11
          相关资源
          最近更新 更多