98:
Given a binary tree, determine if it is a valid binary search tree (BST).
Assume a BST is defined as follows:
- The left subtree of a node contains only nodes with keys less than the node's key.
- The right subtree of a node contains only nodes with keys greater than the node's key.
- Both the left and right subtrees must also be binary search trees.
Example 1:
2 / \ 1 3Binary tree
[2,1,3]
, return true.
Example 2:
1 / \ 2 3Binary tree
[1,2,3]
, return false.
题目意思很明确,就是判断一个树是不是一个二分搜索树,二分搜索树的一个典型特征就是对于每一个内部节点,其左边子树的所有节点值都要小于这个内部节点的值,这也就是我们判断的依据。
一个方法,直接中序遍历,如果合法则必定后一个值大于前一个值,否则返回false。
我使用了另一个大同小异的方法,给每一个节点都设置一个范围,如果这个节点的值满足这个范围则是合法的,否则返回false,那么这个范围怎么设置呢?二分搜素树的典型特征,一个节点的左子节点必然小于自己,但不会小于自己的下限,右子节点大于自己,但不会大于自己范围的上限。例如根节点的范围设置为负无穷到正无穷,那么它的左子节点的范围就是负无穷到根节点的值,右子节点的范围就是根节点的值到正无穷,以此类推。
两种方法的时间复杂度都是O(N)所以应该区别不大。代码如下:
/**
* 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:
long long infinit=21474836499;
long long minfinit=-2147483699;//因为样例的值会达到int的上下限值
bool isValidBST(TreeNode* root) {
if(root==NULL)
return true;
if(root->left==NULL&&root->right==NULL)
return true;
return isValid(root,infinit,minfinit);
}
bool isValid(TreeNode* root,long long ma,long long mi)
{
if(root->val<ma&&root->val>mi)
{
if(root->left==NULL&&root->right==NULL)
return true;
if(root->left!=NULL)
{
if(!isValid(root->left,root->val,mi);)
return false;
}
if(root->right!=NULL)
{
if(!isValid(root->right,ma,root->val);)
return false;
}
return true;
}
else
return false;
}
};
下面是此题用时最少的一个解法,直接从leetcode上copy下来的:
int key=[](){
std::ios::sync_with_stdio(false);
return 0;
}();
class Solution {
public:
int temp;
bool temp_exist=false;
bool isValidBST(TreeNode* root) {
if(!root)
return true;
if(!isValidBST(root->left))
return false;
if(!temp_exist){
temp=root->val;
temp_exist=true;
}
else if(root->val>temp)
temp=root->val;
else
return false;
if(!isValidBST(root->right))
return false;
return true;
}
};
其实这就是一个中序遍历的方法,然后从第一个值开始比较,如果出现小于前一个值的则返回false。
99. Recover Binary Search Tree
Two elements of a binary search tree (BST) are swapped by mistake.
Recover the tree without changing its structure.
Note:A solution using O( n) space is pretty straight forward. Could you devise a constant space solution?
题目告诉我们一个二分搜索树的两个值错位了,我们需要将这两个值换回去。问题的解决依旧可以使用中序遍历,找到两个错误的值应该不难,问题就变成了一个递增序列中有两个值的位置错位了,那么则必然说明有一个数大于它后面的数,还有一个数小于它前面的数,这两个数就是错位的两个。问题瞬间被简化。
代码如下:
/**
* 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:
long long a=-2147483699,b;
TreeNode* para_node;//作为一个参考节点
TreeNode* wrong[2];//保存错位点的地址
void recoverTree(TreeNode* root) {
mid_order(root);
int temp=wrong[0]->val;
wrong[0]->val=wrong[1]->val;
wrong[1]->val=temp;
return;
}
void mid_order(TreeNode* root)
{
if(root!=NULL)
{
mid_order(root->left);
if(a==-2147483699)
{
a=root->val;
para_node=root;
}
else
{
b=root->val;
if(b<a)
{
if(wrong[0]==NULL)//初始化
{
wrong[0]=para_node;
wrong[1]=root;
}
else
{
wrong[1]=root;
return;
}
}
a=b;
para_node=root;
}
mid_order(root->right);
}
}
};