1. 程式人生 > 其它 >二叉樹——判斷是否是搜尋二叉樹和完全二叉樹

二叉樹——判斷是否是搜尋二叉樹和完全二叉樹

1. 判斷一棵二叉樹是否為搜尋二叉樹和完全二叉樹

驗證二叉搜尋樹

二叉樹的完全性檢驗

1.1. 問題

給定二叉樹的一個頭節點 head,已知其中沒有重複值的節點,實現兩個函式分別判斷這棵二叉樹是否為搜尋二叉樹和完全二叉樹。

1.2. 思路

判斷是否是搜尋二叉樹可用中序遍歷一遍,倘若是遞增序列,則為搜尋二叉樹。

判斷是否是完全二叉樹:

  • 方法一:可以用層序遍歷(廣度優先),當發現一個節點的左子節點或右子節點為空時,那麼接下來都不能在遇到子節點。

  • 方法二:可以用深度優先搜尋。一個完全二叉樹可以表示為一個堆,我們在進行遍歷的時候給二叉樹的節點進行編號,然後將最大編號跟節點數量進行比較,如果相同則是完全二叉樹,不同那麼則不是。

判斷一個樹是否為完全搜尋二叉樹時,可以將判斷搜尋二叉樹的方法和判斷完全二叉樹的方法二進行合併。

1.3. 程式碼

1.3.1. 判斷是否為搜尋二叉樹

手動用棧模擬

    public static boolean isBST(TreeNode<Integer> root) {
        if (root == null) return true;
        Stack<TreeNode<Integer>> stack = new Stack<>();
        TreeNode<Integer> cur = root;
        TreeNode<Integer> pre = null;
        while (!stack.empty() || cur != null) {
            if (cur != null) {
                stack.push(cur);
                cur = cur.left;
            } else {
                cur = stack.pop();
                if (pre != null && pre.val > cur.val)
                    return false;
                pre = cur;
                cur = cur.right;
            }
        }
        return true;
    }

遞迴

class Solution {
    private long previousNodeVal = Long.MIN_VALUE;

    public boolean isValidBST(TreeNode root) {
        if(root == null) {
            return true;
        }

        if(!isValidBST(root.left)) {
            return false;
        }

        long val = root.val;
        if(val <= previousNodeVal) {
            return false;
        }
        previousNodeVal = val;

        return isValidBST(root.right);
    }
}

遞迴的分支優化

當一個方法中有很多檢查語句,不通過返回false的話,那麼我們可以將整個方法預設返回false,只用聚焦在返回為true的情況,這樣會讓程式碼更清晰。

class Solution {
    double last = -Double.MAX_VALUE;

    public boolean isValidBST(TreeNode root) {
        if (root == null) {
            return true;
        }
        if (isValidBST(root.left)) {
            if (last < root.val) {
                last = root.val;
                return isValidBST(root.right);
            }
        }
        return false;
    }
}

1.3.2. 判斷是否為完全二叉樹

廣度優先(層序遍歷)

    public static boolean isCBT(TreeNode<Integer> root) {
        if (root == null) return true;
        Queue<TreeNode<Integer>> queue = new LinkedList<>();
        TreeNode<Integer> node = root;
        queue.add(node);
        boolean isChildAllowed = true;
        while (!queue.isEmpty()) {
            node = queue.remove();
            if (node.left != null) {
                if (!isChildAllowed) return false;
                queue.add(node.left);
            } else {
                isChildAllowed = false;
            }

            if (node.right != null) {
                if (!isChildAllowed) return false;
                queue.add(node.right);
            } else {
                isChildAllowed = false;
            }
        }
        return true;
    }

深度優先

class Solution {
    private int count = 0;
    private int maxNum = 0;

    public  boolean isCompleteTree(TreeNode root) {
        if(root == null) {
            return true;
        }
        dfs(root, 1);
        return count == maxNum;
    }

    private void dfs(TreeNode head, int num) {
        count++;
        maxNum = Math.max(maxNum, num);
        if(head.left != null) {
            dfs(head.left, num * 2);
        }
        if(head.right != null) {
            dfs(head.right, num * 2 + 1);
        }
    }