1. 程式人生 > >從定義出發,理解二叉搜尋樹

從定義出發,理解二叉搜尋樹

[leetcode Validate Binary Search Tree]從定義出發,理解二叉搜尋樹

96 書呆子的復仇 關注

2015.12.13 12:53* 字數 855 閱讀 181評論 0喜歡 2

附上原題:

一棵二叉樹如果屬於二叉搜尋樹,必須滿足三個條件:

  1. 左子樹的所有節點都小於根節點
  1. 右子樹的所有節點都大於根節點
  2. 左子樹跟右子樹同時也是二叉搜尋樹

我們看到第三條定義本身也是遞迴的。那根據該定義,如何來檢驗一棵二叉樹到底是不是二叉搜尋樹?

首先,如果左子樹跟右子樹其中有一棵不是二叉搜尋樹的情況下,則該二叉樹必定不屬於二叉搜尋樹。那如何判定左子樹跟右子樹是不是二叉搜尋樹呢?好像我們又回到了原來的問題。看一種比較特殊的情況,假如說二叉樹只有一個節點,即沒有左子樹也沒有右子樹,那麼它必定屬於二叉搜尋樹。如果左子樹不存在,右子樹存在的情況下呢?此時左子樹就不需要再考慮是不是二叉搜尋樹了。反之右子樹不存在的情況下也一樣。

因此,對於這個問題,我們可以先考慮一棵二叉樹的葉子節點。比如說有這樣一棵二叉樹:

 

 

左子樹跟右子樹都屬於葉子節點,必定是二叉搜尋樹。在符合第三條定義的情況下,再來看前面兩條。根節點大於左子樹的所有節點,難道要用根節點與左子樹的每個節點去比較?我們換個角度想,是不是隻要根節點大於左子樹最大的節點就可以了?因為在確定左子樹屬於二叉搜尋樹的情況下,只要沿著左子樹的根節點出發一直向右即可找到最大的節點。同樣,對於第二個定義,根節點只需小於右子樹最小的節點即可。

我們運用了一種“分而治之”的思想,先考慮最基本的情況,即葉子節點,再得到左子樹和右子樹同時為二叉搜尋樹的前提下,用當前樹的根節點去比較左子樹的最大值和右子樹的最小值。然後演算法不斷得往上回溯,最終得出整棵樹是不是二叉搜尋樹。

根據以上分析,我們設計出如下演算法:

  1. 如果當前節點即不存在左子樹也不存在右子樹,直接返回true。
  1. 如果當前節點存在左子樹,則驗證左子樹是否為二叉搜尋樹,若是,並且根節點大於左子樹的最大值,則左子樹驗證通過。若左子樹不存在,同樣驗證通過。
  2. 如果當前節點存在右子樹,則驗證右子樹是否為二叉搜尋樹,若是,並且根節點小於右子樹的最小值,右子樹驗證通過。若右子樹不存在,同樣驗證通過。
  3. 若左子樹跟右子樹同時驗證通過,返回true;否則,返回false。

看程式碼:

class Solution {
public:
    bool isValidBST(TreeNode* root) {

        bool isValidLeft = true;
        bool isValidRight = true;
        if (root) {
            int val = root->val;
            if (root->left) {
                //驗證左子樹是否為二叉搜尋樹,並且根節點大於左子樹的最小值
                isValidLeft = isValidBST(root->left) && (val > fetchMaxNodeVal(root->left));
            }
            if (root->right) {
                isValidRight = isValidBST(root->right) && (val < fetchMinNodeVal(root->right));
            }

            if (!root->left && !root->right) {
                return true;
            }
        }
        return isValidLeft && isValidRight;
    }
private:
    //獲取二叉樹的最大值
    int fetchMaxNodeVal(TreeNode *node) {
        while (node->right) {
            node = node->right;
        }
        return node->val;
    }

    int fetchMinNodeVal(TreeNode *node) {
        while (node->left) {
            node = node->left;
        }
        return node->val;
    }
};

小禮物走一走,來簡書關注我