LeetCode HOT 100:驗證二元搜尋樹(從左右子樹獲取資訊進行推導)

2023-01-05 12:00:52

題目:98. 驗證二元搜尋樹

題目描述:

給你一個二元樹,讓你判斷該二元樹是否是二元搜尋樹。什麼是二元搜尋樹呢?就是某一個節點的左子樹上的所有節點的值都小於當前節點,右子樹上的所有節點值都大於當前節點,記住,是所有節點,不是左子節點和右子節點這倆節點。而且樹上所有的節點都必須滿足這個條件,整棵樹才能是二元搜尋樹。

思路:

這道題提供兩種思路,第二種也很妙。
1、思路一其實很簡單,也很常見。對於二元搜尋樹來說,該樹的中序遍歷一定是一個遞增的陣列,所以可以在中序遍歷的時候判斷是否遞增就行。實現方式很多,有的是遍歷節點的時候將其放到一個陣列中,最終看這個陣列是否是遞增的。有的優化版本,不用陣列,直接來一個變數記錄上一節點的值,不斷比較前一節點和當前節點的大小,都是可以的。
2、思路二是一種拓展模版,就是可以用這種思路解決很多二元樹的問題。思路就是:如果碰到二元樹題中,當前節點需要根據左右子樹提供的資訊來推匯出當前節點的資訊,那麼就可以使用該思路。比如這道題,驗證二元搜尋樹,其實就是驗證每一個節點是否滿足二元搜尋樹的節點要求。而滿足要求的節點需要滿足三個條件:

  • 當前節點要大於左子樹上所有節點的最大值
  • 當前節點要小於右子樹上所有節點的最小值
  • 當前節點的左右子樹都必須是二元搜尋樹

所以,從左子樹上需要的值就是左子樹的最大值和左子樹是否是二元搜尋樹,從右子樹上需要的值就是右子樹的最小值和右子樹是否是二元搜尋樹。兩個一合併,從左右子樹需要的資訊就是最大值、最小值、是否是二元搜尋樹
下一步就是根據左右子樹提供的這三個資訊,推匯出當前節點的這三個資訊。最大值,可以將左右子樹的最大值和當前節點值比較之後得到;最小值同理;當前節點是否是二元搜尋樹,可以根據左右子樹是否都是二元搜尋樹來得到。最終一層層節點,向上提供資訊,最終,根節點的資訊就推匯出來了,是否滿足二元搜尋樹,自然而然就出來了!
這種思路用來解決這一題,可能沒有中序遍歷那麼簡單。但是這種思路可以解決很多二元樹的問題,是一種模版思想,這是很珍貴的一點。如果碰到二元樹題中,當前節點需要根據左右子樹提供的資訊來推匯出當前節點的資訊,那麼就可以使用該思路。 碰到不知道怎麼解決的二元樹題,可以思路往這上面靠攏,或許就有思路了。

步驟:

1、構建從左右子樹需要的資訊。建立一個Info類,裡面包含,最大值、最小值、是否是二元搜尋樹
2、遞迴方法中,先去獲取左子樹和右子樹的Info資訊,拿到之後,開始構建當前節點的Info資訊。
3、遞迴方法完畢,返回根節點的Info資訊,返回資訊中的是否是二元搜尋樹屬性即可。

程式碼:

思路一的程式碼:

    // 用來記錄前一個節點
    TreeNode pre;
    public boolean isValidBST2(TreeNode root) {
        if (root == null) return true;

        // 左
        boolean left = isValidBST2(root.left);

        // 中
        // 如果不遞增了
        if (pre != null && pre.val >= root.val) return false;
        pre = root;

        // 右
        boolean right = isValidBST2(root.right);

        return left && right;
    }

思路二的程式碼:

    public boolean isValidBST(TreeNode root) {
        return process(root).isBST;
    }

    public Info process(TreeNode node) {
        if (node == null) return null;

        // 從左右子樹中獲取資訊
        Info leftInfo = process(node.left);
        Info rightInfo = process(node.right);

        boolean isBST = true;
        int min = node.val;
        int max = node.val;

        // 構建當前節點的資訊
        if (leftInfo != null) {
            max = Math.max(leftInfo.max, max);
            min = Math.min(leftInfo.min, min);

            if (!leftInfo.isBST || leftInfo.max >= node.val) {
                isBST = false;
            }
        }
        if (rightInfo != null) {
            max = Math.max(rightInfo.max, max);
            min = Math.min(rightInfo.min, min);

            if (!rightInfo.isBST || rightInfo.min <= node.val) {
                isBST = false;
            }
        }

        return new Info(isBST, min, max);
    }

    class Info {
        boolean isBST;
        int min;
        int max;

        public Info(boolean isBST, int min, int max) {
            this.isBST = isBST;
            this.min = min;
            this.max = max;
        }
    }