問題描述:
給定一個二叉樹,判斷其是否是一個有效的二叉搜索樹。
假設一個二叉搜索樹具有如下特徵:
節點的左子樹只包含小於當前節點的數。
節點的右子樹只包含大於當前節點的數。
所有左子樹和右子樹自身必須也是二叉搜索樹。
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/validate-binary-search-tree
示例 1:
輸入:
2
/ \
1 3
輸出: true
示例 2:
輸入:
5
/ \
1 4
/ \
3 6
輸出: false
解釋: 輸入爲: [5,1,4,null,null,3,6]。
解題思路:
首先我們看到題意,左子樹<根節點<右子樹
自然而然就會想到中序遍歷
首先我們來看看中序遍歷的代碼(遞歸算法)
void inorder(Tree T){
if (T) {
inorder(T->lchild);//遍歷左孩子
visit(T);//調用操作結點數據的函數方法
inorder(T->rchild);//遍歷右孩子
}
//如果結點爲空,返回上一層
return;
}
這裏我們發現,如果該樹是二叉搜索樹,那麼中序遍歷得到的序列是有序遞增序列
這個時候我們用一個數組存儲中序遍歷序列,然後判斷該序列是否爲有序遞增序列即可,代碼如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
vector<int> res;
bool isValidBST(TreeNode* root) {
inorder(root);
if(res.size()==1) return true;
for(int i=1;i<res.size();i++){
if(res[i]<=res[i-1]) return false;
}
return true;
}
void inorder(TreeNode* root) {
if(root){
inorder(root->left);
res.push_back(root->val);
inorder(root->right);
}
}
};
這裏額外開闢了數組,其空間複雜度爲O(n)
其實可以更加優化一下,
我們設想一下,如果在遍歷過程中,我們使用節點pre來存儲前一個訪問的節點,然後判斷現訪問節點和pre的值,即可
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* pre = NULL;
bool isValidBST(TreeNode* root) {
return inorder(root);
}
bool inorder(TreeNode* root) {
if(root == NULL){
return true;
}
if(!inorder(root->left)) return false;
if(pre !=NULL && root->val <= pre->val) return false;
pre = root;
return inorder(root->right);
}
};