解法一:前序遍历 树形dp
前序遍历是最常见的遍历方式,此处也是可以使用的。我们每次记录左子树和右子树的最大值和最小值。
返回后,我们只需判断左子树和最大值是否小于中间值,或右子树的最小值是否大于最小值即可。
typedef long long ll;
class Solution {
typedef vector<ll> V;
public:
V dfs(TreeNode *n)
{
if(!n)return V{1, (ll)INT_MAX+1, (ll)INT_MIN-2};
V l = dfs(n->left), r = dfs(n->right);
if(!l[0] || !r[0])return V{0, 0, 0};
if(l[2] >= n->val || r[1] <= n->val)return V{0, 0, 0};
return V{1, min({(ll)n->val, l[1], r[1]}), max({(ll)n->val, l[2], r[2]})};
}
bool isValidBST(TreeNode* root) {
return dfs(root)[0];
}
};
解法二:中序遍历
此做法是常数复杂度更低的做法,少了比较,只需每次维护一个最大值即可。这也是由中序遍历的特点决定的。
class Solution {
typedef long long ll;
public:
bool judge(ll &mx, TreeNode *n)
{
if(!n)return true;
if(!judge(mx, n->left))return false;
if(n->val <= mx)return false;
mx = n->val;
return judge(mx, n->right);
}
bool isValidBST(TreeNode* root) {
ll mx = LLONG_MIN;
return judge(mx, root);
}
};