今天刷题的内容是二分搜索树的内容;
首先是二分搜索树的概念:二分搜索树是一种高效的二叉树,任何结点的左结点都小于根节点,右节点都大于根节点;
具有高效的find功能;
二分搜索树的使用在leetcode中也有不少题,下面就对相应的二分搜索树的内容做yield归纳:
leetcode235:求一个二分搜索树的最近的公共父亲结点; 使用递归来进行实现算法;
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
//使用二分搜索树的特点,根据值进行分段,然后判断相应的递归停止条件
if(root==NULL){
return NULL;
}
if(p->val==root->val||q->val==root->val){
return root;
}
if(p->val>root->val&&q->val<root->val||p->val<root->val&&q->val>root->val){
return root;
}
if(p->val>root->val&&q->val>root->val){
return lowestCommonAncestor(root->right, p, q);
}
if(p->val<root->val&&q->val<root->val){
return lowestCommonAncestor(root->left, p, q);
}
}
};
leetcode98:验证一棵树是否是二分搜索树;
class Solution {
public:
bool isValidBST(TreeNode* root) {
//采用中序遍历的思想
stack<TreeNode *> ss;
TreeNode *p=root;
int pre;
int curr;
bool flag=true;
while(p!=NULL||!ss.empty()){
while(p!=NULL){
ss.push(p);
p=p->left;
}
if(!ss.empty()){
TreeNode * node=ss.top();
ss.pop();
p=node->right;
curr=node->val;
if(flag){
flag=false;
pre=curr;
continue;
}
if(curr<=pre){//之前的结点的值要比现在的结点的值来的小才是符合结果的否则就
return false;
}
pre=curr;
}
}
return true; }
解决思路采用中序遍历的方式,后来采用递归算法来分析发现不行;
leetcode108:将有序数组构建成一颗平衡的二分搜索树;
class Solution {
public:
TreeNode* sortedArrayToBST(vector<int>& nums) {
//通过递归的方法构建相应的二分搜索树;
//提议要求树的结构是平衡的,也就是说所构建的二分搜索树是平衡树;
int size=nums.size();
if(size==0){
return NULL;
}
if(size==1){
TreeNode *root=new TreeNode(nums[0]);
return root;
}
int mid=(size-1)/2;
vector<int> left_num(nums.begin(),nums.begin()+mid);
vector<int> right_num(nums.begin()+mid+1,nums.end());
TreeNode *root=new TreeNode(nums[mid]);
root->left=sortedArrayToBST(left_num);
root->right=sortedArrayToBST(right_num);
return root;
}
};
leetcode230: 输出二叉搜索树中的第k小的 元素;
思路采用中序遍历的方式,中序遍历的三种方式来实现;
struct command{
string flag;
TreeNode* Node;
command(string s,TreeNode* node):flag(s),Node(node){}
};
class Solution {
public:
int kthSmallest(TreeNode* root, int k) {
// //解决方法,采用中序遍历的方式,中序遍历二分搜索树,首先将结果保存在vector<int>中
// //采用栈模拟的递归方式
// //面向对象的方式来实现
// stack<command> ss;
// ss.push(command("go",root));
// vector<int> ans;
// while(!ss.empty()){
// command top=ss.top();
// ss.pop();
// if(top.flag=="cout"){
// ans.push_back(top.Node->val);
// }
// else{
// if(top.Node->right!=NULL){
// ss.push(command("go",top.Node->right));}
// ss.push(command("cout",top.Node));
// if(top.Node->left!=NULL){
// ss.push(command("go",top.Node->left));}
// }
// }
// // int size=ans.size();
// return ans[k-1];
//不采用模拟栈的方式,模拟栈的方式比较简单
//手动实现栈的方式来实现
// 1.首先是定义根节点;
// 2.定义一个栈;
TreeNode* p=root;
if(p==NULL){
return 0;
}
vector<int> ans;
stack<TreeNode*> ss;
while(!ss.empty()||p!=NULL){
while(p!=NULL){
ss.push(p);
p=p->left;
}
if(!ss.empty()){
TreeNode *top=ss.top();
ans.push_back(top->val);
ss.pop();
p=top->right;
}
}
return ans[k-1];
}
};
leetcode95: 求能够组成的二分搜索树的棵树,也就是说能有多少棵二分搜索树
问题描述:
Given an integer n, generate all structurally unique BST's (binary search trees) that store values 1 ... n.
Example:
Input: 3 Output: [ [1,null,3,2], [3,2,null,1], [3,1,null,null,2], [2,1,3], [1,null,2,null,3] ] Explanation: The above output corresponds to the 5 unique BST's shown below: 1 3 3 2 1 \ / / / \ \ 3 2 1 1 3 2 / / \ \ 2 1 2 3
解题思路就是递归实现
vector<TreeNode*> generateTrees(int n) {
//如何得到相应的二分搜索树 递归实现看看
vector<TreeNode*> ans;
if(n==0){
return ans;
}
if(n==1){
ans.push_back(new TreeNode(1));
return ans;
}
return generate(1,n);//左闭有闭的方式
}
vector<TreeNode*> generate(int begin,int end){
vector<TreeNode*> ans;
if(begin==end){
ans.push_back(new TreeNode(begin));
return ans;
}
if(begin>end){
ans.push_back(NULL);
return ans;
}
for(int i=begin;i<=end;i++){
vector<TreeNode*> left=generate(begin,i-1);
vector<TreeNode*> right=generate(i+1,end);
for(int j=0;j<left.size();j++){
for(int k=0;k<right.size();k++){
TreeNode* root=new TreeNode(i);
root->left=left[j];
root->right=right[k];
ans.push_back(root);
}
}
}
return ans;
}
python实现:
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def generateTrees(self, n):
"""
:type n: int
:rtype: List[TreeNode]
"""
ans=[]
if(n==0):
#ans.append(None)
return ans
if(n==1):
ans.append(TreeNode(1))
return ans;
return self.generate(1,n)
def generate(self,begin,end):#实例方法
ans=[]
if(begin==end):
ans.append(TreeNode(begin))
return ans
if(begin>end):
ans.append(None)
return ans
for i in range(begin,end+1):# range(begin,end) 是左闭右开的range内容;
leftans=self.generate(begin,i-1)
rightans=self.generate(i+1,end)
for j in range(len(leftans)):
for k in range(len(rightans)):
root=TreeNode(i)
root.left=leftans[j]
root.right=rightans[k]
ans.append(root)
return ans
95:续上题 采用动态规划来得到相应的二分搜索树的棵树;
int numTrees(int n) {
//分析使用动态规划的解题思路
//对于i的二分搜索树的计算方式是: 当以i作为根节点是 temp[i]=dp[i-1] 以i-1作为根节点是此时左子树中的树有dp[i-2],temp[i-1]=dp[i-2]*dp[1]
//对于以i-2作为根节点的树有 temp[i-2]=dp[i-3]*dp[2] 对于一般的情况对于以i-k作为跟节点时 temp[i-k]=dp[i-k-1]*dp[k]
//下面是代码实现
vector<int> dp(n+1,0);
dp[0]=1;
dp[1]=1;
for(int i=2;i<=n;i++){
for(int j=0;j<i;j++){
dp[i]+=dp[i-j-1]*dp[j];
}
}
return dp[n];
}