今天刷题的内容是二分搜索树的内容;
首先是二分搜索树的概念:二分搜索树是一种高效的二叉树,任何结点的左结点都小于根节点,右节点都大于根节点;
具有高效的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]; }