簡體   English   中英

查找樹是否平衡的迭代解決方案

[英]Iterative Solution to finding if a tree is balanced

所以有人發布了他們的解決方案,但我發現它似乎不起作用,我將其發布在那里,但我想讓其他人更容易訪問它。

題目在“Cracking the Code Interview”中,是第一個樹題,歡迎提出其他建議(或證明我錯了!)

這里的關鍵是很難通過一堆來跟蹤最終的路徑及其高度。

我最終要做的是將左右孩子的身高同時推入堆棧,檢查它們的高度是否在彼此之間,將最大值加一,然后在彈出左右鍵之后將其推入堆棧。

我已發表評論,所以我希望它足夠清楚

 /* 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;
        }

書中最初的問題沒有提到樹是二進制的。 我碰巧解決了同樣的問題,但是用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 )保留了單獨的堆棧。 如果看到任何葉節點,我們將相應地更新當前的最小和當前的最大級別。 該算法遍歷整棵樹,最后如果最大和最小級別相差一個以上,則樹不平衡。

有許多優化可能,例如檢查循環內的最小值和最大值之差是否大於一,如果是這種情況,請立即返回False

在此代碼上重復一些代碼,但至少不會像遞歸代碼那樣讓我頭疼:

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;
}

所以最后我設法創建了一個迭代解決方案,適用於Leetcode上的所有測試用例

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public static boolean isBalanced(TreeNode root) {
        if (root == null) return true;
        Deque<Pair> queue = new LinkedList<>();
        queue.offer(new Pair(root, 0));
        while (!queue.isEmpty()) {

            var curr = queue.poll();
            System.out.printf(">>Curr node is %s and curr.lvl is %s", curr.node.val, curr.lvl);
            int left = getSubTreeHeight(new Pair(curr.node.left, curr.lvl + 1));
            int right = getSubTreeHeight(new Pair(curr.node.right, curr.lvl + 1));

            if (Math.abs(left - right) > 1) return false;

            if (curr.node.left != null) queue.offer(new Pair(curr.node.left, curr.lvl + 1));
            if (curr.node.right != null) queue.offer(new Pair(curr.node.right, curr.lvl + 1));

        }
        return true;
    }
    static int getSubTreeHeight(Pair pair) {
        if (pair.node == null) {
            return pair.lvl -1;
        }
        Deque<Pair> queue = new LinkedList<>();
        queue.offer(pair);
        int height = 0;
        while (!queue.isEmpty()) {
            Pair curr = queue.poll();
            System.out.printf("Curr node is %s and curr.lvl is %s", curr.node.val, curr.lvl);
            height = curr.lvl;
            if (curr.node.left != null) queue.offer(new Pair(curr.node.left, curr.lvl + 1));
            if (curr.node.right != null) queue.offer(new Pair(curr.node.right, curr.lvl + 1));
        }
        return height;
    }


   public static class Pair {
       TreeNode node;
       int lvl;
       public Pair(TreeNode node, int lvl) {
           this.node = node;
           this.lvl = lvl;
       }
   }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM