98. 驗證二叉搜索樹(二叉樹的遍歷)

下面這個題雖然是二叉搜索樹,但本質上仍然是遍歷樹,並且中序遍歷二叉搜索樹是得到的排列是有序的,我們可以考慮用中序遍歷解決這一問題。

98. 驗證二叉搜索樹

假設一個二叉搜索樹具有如下特徵:

  • 節點的左子樹只包含小於當前節點的數。
  • 節點的右子樹只包含大於當前節點的數。
  • 所有左子樹和右子樹自身必須也是二叉搜索樹。

示例 1:

輸入:
    2
   / \
  1   3
輸出: true

示例 2:

輸入:
    5
   / \
  1   4
     / \
    3   6
輸出: false
解釋: 輸入爲: [5,1,4,null,null,3,6]。
     根節點的值爲 5 ,但是其右子節點值爲 4 。

1、遞歸遍歷縮小區間

class Solution {
    bool isValidBSThelper(TreeNode* root, long long low, long long high){
        if(root == nullptr) return true;
        //節點值嚴格在開區間內
        if(root->val <= low || root->val >= high) return false;
        return isValidBSThelper(root->left, low, root->val) && isValidBSThelper(root->right, root->val, high);
    }
public:
    bool isValidBST(TreeNode* root) {
        //開始區間兩邊分到取到long所能表示的最大值和最小值
        return isValidBSThelper(root, LONG_MIN, LONG_MAX);
    }
};

2.利用BST中序遍歷的性質(遞歸做法)

class Solution {
    //記錄中序遍歷root前一個節點的val,有點線索二叉樹的意思
    long long pre = (long long)INT_MIN - 1;
public:
    bool isValidBST(TreeNode* root) {
        //空樹也是二叉搜索樹 或者 搜索到葉子節點就返回
        if(root == nullptr){
            return true;
        }
        //訪問BST的左子樹,如果左子樹不是BST,直接返回flase
        if(!isValidBST(root->left)){
            return false;
        }
        //遞歸回來之後,pre已是root左子樹中最大的元素
        //判斷當前節點,是否滿足BST的性質
        if(pre >= root->val){
            return false;
        }
        //改變pre的值,準備訪問BST的右子樹
        pre = root->val;
        //訪問BST
        return isValidBST(root->right);
    }
};

3.利用BST中序遍歷的性質(非遞歸做法)

參考樹的遍歷

class Solution {
public:
    bool isValidBST(TreeNode* root) {
        //記錄中序遍歷root前一個節點的val
        long long pre = (long long)INT_MIN - 1;
        stack<TreeNode*> stack;
        while(!stack.empty() || root != nullptr){
            //一路向左下
            while(root != nullptr){
                stack.push(root);
                root = root->left;
            }
            //此時棧頂爲左下節點,訪問完後,訪問右子樹
            root = stack.top();
            stack.pop();
            //不滿足BST性質,結束
            if(root->val <= pre){
                return false;
            }
            pre = root->val;
            //準備遍歷右子樹
            //不要直接壓棧,萬一當前節點沒有右子樹呢
            root = root->right;
        }
        return true;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章