数据结构与算法以及leetcode刷题 012 二分搜索树

今天刷题的内容是二分搜索树的内容;

首先是二分搜索树的概念:二分搜索树是一种高效的二叉树,任何结点的左结点都小于根节点,右节点都大于根节点;

具有高效的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];
    }

猜你喜欢

转载自blog.csdn.net/hufanglei007/article/details/79587365