二分查找与二叉树排序

本文详细介绍了二分查找的递归和循环实现,包括在LeetCode中的应用,如搜索插入位置和区间查找。同时,讨论了处理边界条件和更新区间的技巧。此外,还探讨了旋转数组查找的难点和解决策略。最后,讲解了二叉查找树的插入、编码和解码,以及在逆序数问题中的应用。文章通过实例展示了如何在复杂场景下运用二分查找算法及其变体。
摘要由CSDN通过智能技术生成

知识点【二分查找】

二分查找【递归】

二分查找【循环】

有回溯时候最好递归

两种代码模式要掌握会写!

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

一,插入位置

LeetCode 35. Search Insert Position

1.处理边界

2.二分基本框架

3.别忘了更新区间

4.循环判断的越界条件一定要放在最开头【重点】

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int index=-1;
        int begin=0;
        int end=nums.size()-1;
        while(index==-1)
        {
            int mid=(begin+end)/2;
            if(nums[mid]==target)
            {
                index=mid;
            }
            else if(target<nums[mid])
            {
                if(mid==0||target>nums[mid-1])
                {
                    index=mid;
                }
                end=mid-1;//别忘了更新区间啊
            }
            else if(target>nums[mid])
            {
                if(mid==nums.size()-1||target<nums[mid+1])
                {
                    index=mid+1;
                }
                begin=mid+1;
            }
        }
        return index;
    }
};

作者:xia-mu-lao-zhang-ren
链接:https://leetcode-cn.com/problems/search-insert-position/solution/cha-ru-wei-zhi-by-xia-mu-lao-zhang-ren-90l1/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

二,区间查找

LeetCode 34. Search for a Range

1.把求区间【拆解】成左右端点

2.处理边界

3.给二分查找加限制条件

4.函数内部不能定义函数,之前写在类的内部了

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

int right_bound(vector<int>&nums,int target){
        int begin=0;
        int end=nums.size()-1;
        while(begin<=end)
        {
            int mid=(begin+end)/2;
            if(nums[mid]==target)
            {
                if(mid==nums.size()-1||nums[mid+1]>target)//限制条件,边界写前面,防止越界
               {
                   return mid;
               }
                 begin=mid+1;//重要一步给忘了【紧随其后调整】
            }
           
            else if(target<nums[mid])
            {
                end=mid-1;
            }
            else if(target>nums[mid])
            {
                begin=mid+1;
            }
        }
        return -1;
       }
int left_bound(vector<int>&nums,int target){
           int begin=0;
           int end=nums.size()-1;
           while(begin<=end)
           {
               int mid=(begin+end)/2;
               if(nums[mid]==target)
               {
                   if(mid==0||nums[mid-1]<target)                  
                   {
                       return mid;
                   }
                   end=mid-1;//重要一步
               }
               else if(target<nums[mid])
               {
                   end=mid-1;
               }
               else if(target>nums[mid])
               {
                   begin=mid+1;
               }
           }
           return -1;
       }
class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {                 
       vector<int>result;
       result.push_back(left_bound(nums,target));
       result.push_back(right_bound(nums,target));
       return result;      
    }
};

作者:xia-mu-lao-zhang-ren
链接:https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/solution/cha-zhao-qu-jian-by-xia-mu-lao-zhang-ren-fjwq/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

三,旋转数组查找【没理解】

LeetCode 33. Search in Rotated Sorted Array
两个接上?》首尾相连
判断旋转区间
边界情况
情况很多很复杂
4.【精髓】将数组一分为二,其中一定有一个是有序的,另一个可能是有序,也能是部分有序。
此时有序部分用二分法查找。无序部分再一分为二,其中一个一定有序,另一个可能有序,可能无序。就这样循环
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

class Solution {
public:
    int search(vector<int>& nums, int target) {       
        int n=nums.size();
        int begin=0;
        int end=n-1;
        if(!n){
            return -1;
        }
        if(n==1){
            return nums[0]==target?0:-1;
        }
        while(begin<=end){
            int mid=(begin+end)/2;
            if(target==nums[mid]){
                return mid;
            }
            if(nums[0]<=nums[mid]){//左半边有序
                if(target>=nums[0]&&target<nums[mid]){//target在左半边
                    end=mid-1;
                }
                else//在右半边
                    begin=mid+1;
            }
            else//右半边有序 
            {
                if(target>nums[mid]&&target<=nums[end]){
                    begin=mid+1;
                }
                else
                    end=mid-1;
            }
            
        }
        return -1;

    }
};

作者:xia-mu-lao-zhang-ren
链接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array/solution/sou-suo-xuan-zhuan-shu-zu-by-xia-mu-lao-dcfpo/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

【知识点】二叉查找(排序)树

1.中序遍历是从小到大的

2.如何插入结点插入到二叉查找树中

3.二叉树查找数值

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

五,二叉查找数的编码和解码

LeetCode 449. Serialize and Deserialize BST

1.二叉查找树前序遍历与复原

2.整形转为字符串

3.字符串拆解整型

4.结点的创建和初始化

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
 void changt_int_to_string(int val,string &str_val){
     string tmp;
     while(val){//一个结点数据
         tmp+=val%10+'0';
         val=val/10;
     }
     for(int i=tmp.length()-1;i>=0;i--){
         str_val+=tmp[i];
     }
     str_val+='#';
 }
 void BST_preorder(TreeNode*node,string &data){
     if(!node){
         return;
     }
     string str_val;
     changt_int_to_string(node->val,str_val);
     data+=str_val;
     BST_preorder(node->left,data);
     BST_preorder(node->right,data);
 }
 void BST_insert(TreeNode*node,TreeNode*insert_node){
     if(insert_node->val<node->val){
         if(node->left){
            BST_insert(node->left,insert_node);
         }
         else{
             node->left=insert_node;
         }        
     }
     else{
         if (node->right){
             BST_insert(node->right,insert_node);
         }
         else{
             node->right=insert_node;
         }
     }
 }
class Codec {
public:

    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        string data;
        BST_preorder(root,data);
        return data;
    }

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        if(data.length()==0){
            return NULL;
        }
        vector<TreeNode*>node_vec;
        int val=0;
        for(int i=0;i<data.length();i++){
            if(data[i]=='#'){
            node_vec.push_back(new TreeNode(val));//有多少#,加多少结点,上一个的val初始化他
            val=0;//初始为0
            } 
            else{
                val=val*10+data[i]-'0';
            }         
        }
        for(int i=1;i<node_vec.size();i++){
            BST_insert(node_vec[0],node_vec[i]);
        }
        return node_vec[0];
    }
};

// Your Codec object will be instantiated and called as such:
// Codec* ser = new Codec();
// Codec* deser = new Codec();
// string tree = ser->serialize(root);
// TreeNode* ans = deser->deserialize(tree);
// return ans;

作者:xia-mu-lao-zhang-ren
链接:https://leetcode-cn.com/problems/serialize-and-deserialize-bst/solution/er-cha-shu-bian-ma-yu-zhuan-ma-by-xia-mu-ppyk/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

六,逆序数(用归并做过)【未解决,超时了】

LeetCode 315. Count of Smaller Numbers After Self
1.分治思想
2.记录左子树数量二叉查找树
3.将元素按照原数组逆置后的顺序插入到二叉查找树中,如何在元素插入时,计算已有多少个元素比当前插入元素小?
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

struct BSNode{
    int val;
    int count;//二叉树中左子树的个数
    BSNode*left;
    BSNode*right;
    BSNode(int x):val(x),left(NULL),right(NULL),count(0){}
};
void BST_insert(BSNode*node,BSNode*insert_node,int &count_small)//当前结点,插入的结点,二叉树中比insert_node小的结点个数
    {
        if(insert_node->val<=node->val)
        {
            node->count++;
            if(node->left)
            {
                BST_insert(node->left,insert_node,count_small);
            }
            else
            {
                node->left=insert_node;
            }
        }
        else
        {
            count_small+=node->count+1;//跑右边去了,把左边的都加上,【带上根结点】
            if(node->right)
            {
                BST_insert(node->right,insert_node,count_small);
            }
            else
            {
                node->right=insert_node;
            }
        }
    }
class Solution { 
public:
    vector<int> countSmaller(vector<int>& nums) {
        vector<int>result;
        vector<BSNode*>node_vec;
        vector<int>count;
        for(int i=nums.size()-1;i>=0;i--)
        {
            node_vec.push_back(new BSNode( nums[i]));//逆置nums数组//【新创建】
        }
        count.push_back(0);//第一个结点count_small=0
        for(int i=1;i<node_vec.size();i++)//从第二个结点开始插
        {
            int count_small=0;
            BST_insert(node_vec[0],node_vec[i],count_small);//从第一个结点开始比较,向下递归
            count.push_back(count_small);//count是记录count_small结果的数组
        }
        for(int i=node_vec.size()-1;i>=0;i--)
        {
            delete node_vec[i];
            result.push_back(count[i]);
        }
        return result;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值