写在前面
给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。
有效 二叉搜索树定义如下:
- 节点的左子树只包含 小于 当前节点的数。
- 节点的右子树只包含 大于 当前节点的数。
- 所有左子树和右子树自身必须也是二叉搜索树。
提示:
- 树中节点数目范围在$[1, 10^4]$ 内
- $-2^{31} \leq Node.val \leq 2^{31} - 1$.
本质上就是中序遍历的应用, 因为二叉搜索树中序遍历的结果是一个严格的单调增序列.
第一种思路:先存数组, 然后判断
这里我一开始想的是集合去重然后判断排序数组, 但是内存飙升.
class Solution {
public:
bool isValidBST(TreeNode* root) {
if (!root) return true;
vector<int> v{};
function<void(TreeNode*)> f = [&](TreeNode* cur) {
if (!cur) return;
f(cur->left);
v.emplace_back(cur->val);
f(cur->right);
};
f(root);
auto vv(v);
set<int> s(v.begin(), v.end());
sort(v.begin(), v.end());
return s.size() == v.size() && v == vv;
}
};
那么接下来的一种改进就是直接判断数组了, 如下:
class Solution {
public:
bool isValidBST(TreeNode* root) {
if (!root) return true;
vector<int> v{};
function<void(TreeNode*)> f = [&](TreeNode* cur) {
if (!cur) return;
f(cur->left);
v.emplace_back(cur->val);
f(cur->right);
};
f(root);
for (int i{1}; i < v.size(); ++i)
if (v[i - 1] >= v[i]) return false;
return true;
}
};
但是还是不是最优解.
第二种思路: 遍历同时比较
遍历时候进行比较, 用到了中序遍历的递归写法:
class Solution {
public:
long pre = INT64_MIN;
bool isValidBST(TreeNode* root) {
if (!root) return true;
bool left = isValidBST(root->left);
if (root->val > pre)
pre = root->val;
else
return false;
bool right = isValidBST(root->right);
return left && right;
}
};
不用最小值也可以:
class Solution {
public:
TreeNode* pre{};
bool isValidBST(TreeNode* root) {
if (!root) return true;
bool left = isValidBST(root->left);
if (pre)
if (root->val > pre->val)
pre = root;
else
return false;
else
pre = root;
bool right = isValidBST(root->right);
return left && right;
}
};
判断部分看起来有点乱, 精简一下:
class Solution {
public:
TreeNode* pre{};
bool isValidBST(TreeNode* root) {
if (!root) return true;
bool left = isValidBST(root->left);
if (pre && root->val <= pre->val) return false;
pre = root;
bool right = isValidBST(root->right);
return left && right;
}
};
顺便巩固一下中序遍历迭代写法:
class Solution {
public:
bool isValidBST(TreeNode* root) {
if (!root) return true;
stack<TreeNode*> st;
TreeNode* pre{};
while (!st.empty() || root) {
if (root) {
st.push(root);
root = root->left;
} else {
root = st.top();
st.pop();
// 操作
if (pre && pre->val >= root->val) return false;
pre = root;
root = root->right;
}
}
return true;
}
};