当前位置: 首页 > news >正文

二分查找【看了包会】

👉目录

一、 题目连接 704. 二分查找 - 力扣(LeetCode)

二、理论学习-基础二分查找

(1)[left, right] 

(2)[left, right) 

三、基础算法总结

四、lower_bound 、 upper_bound、binary_search (推荐)

五、题目练习


        经过两个月(甚至我觉得更久)的挣扎,终于对基本的算法有了一个稍为全面的理解,理论知识+c++语法的不断练习+刷题背诵模版,但是学到最后对最初的简单算法反而有点淡忘了·····自己是真没学算法的天赋,只能不断一遍遍重复努力了·····

        我的问题(不知道大家会不会有):①接触到新算法后对旧的算法就会忘【可能一开始学的时候就懵懵懂懂的···】②做过的题还是不会做【emm所以我才以博客的形式记录,方便回顾,就像高中数学一样,大量无厘头的刷题不如有一个属于自己的错题本!】③看到新题有思路也能写代码但结果不是报错就是写一半写不下去了【自己静不下心emm再加上语法不熟练 知识点不熟练】

     所以我打算从头开始温习一遍(距离保研机试还有差不多5-6月的时间)加油吧!!😃👍

一、 题目连接 704. 二分查找 - 力扣(LeetCode)

二、理论学习-基础二分查找

        写二分法经常写乱,主要是因为对区间的定义没有想清楚,区间的定义就是不变量。要在二分查找的过程中,保持不变量,就是在while寻找中每一次边界的处理都要坚持根据区间的定义来操作,这就是循环不变量规则。

        写二分法,区间的定义一般为两种,左闭右闭即[left, right],或者左闭右开即[left, right)

下面我用这两种区间的定义分别讲解两种不同的二分写法。

(1)[left, right] 

因为定义target在[left, right]区间,所以有如下两点:

  • while (left <= right) 要使用 <= ,因为left == right是有意义的,所以使用 <=
  • if (nums[middle] > target) right 要赋值为 middle - 1,因为当前这个nums[middle]一定不是target,那么接下来要查找的左区间结束下标位置就是 middle - 1
class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left=0;
        int right=nums.size()-1;//[]
        while(left<=right)
        {
            int middle=(left+right)/2;
            if(nums[middle]<target) left=middle+1;
            else if(nums[middle]>target) right=middle-1;
            else return middle;

        }
        return -1;
        
    }
};

(2)[left, right) 

  • while (left < right),这里使用 < ,因为left == right在区间[left, right)是没有意义的
  • if (nums[middle] > target) right 更新为 middle,因为当前nums[middle]不等于target,去左区间继续寻找,而寻找区间是左闭右开区间,所以right更新为middle,即:下一个查询区间不会去比较nums[middle]
class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left=0;
        int right=nums.size();//[ )
        while(left<right)
        {
            int middle=(left+right)/2;
            if(nums[middle]<target) left=middle+1;
            else if(nums[middle]>target) right=middle;
            else return middle;

        }
        return -1;
        
    }
};

三、基础算法总结

①先定义left  right  【区间的定义】

②进入循环 【注意循环条件】

③将target 与 nums[middle] 进行比对,结合①对区间的定义 更新左右区间 【主体部分】

四、lower_bound 、 upper_bound、binary_search (推荐)

C++ STL 提供了 lower_boundupper_bound 进行二分查找,它们位于 <algorithm> 头文件中

binary_search() 只能用于已排序的容器 

如何转换为索引?

  • left - nums.begin() 计算 第一个 target 出现的索引

  • right - nums.begin() - 1 计算 最后一个 target 出现的索引

五、题目练习

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
       int res = lower_bound(nums.begin(),nums.end(),target)-nums.begin();
       return res;
    }
};

 

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        vector<int> res = {-1, -1}; // 默认返回 [-1, -1]
        auto left = lower_bound(nums.begin(), nums.end(), target);
        if (left == nums.end()||*left!=target) { 
            //*left 是该迭代器指向的值可能返回一个大于 target 的元素,而不一定是 target
            return res; // target 不存在,直接返回
        }
        
        auto right = upper_bound(nums.begin(), nums.end(), target);
        
        res[0] = left - nums.begin();
        res[1] = right - nums.begin() - 1;

        return res;
    }
};

789. 数的范围 - AcWing题库 

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n,q;
    cin>>n>>q;
    vector<int> nums(n);
    for(int i=0;i<n;i++) cin>>nums[i];
    while(q--)
    {
        int k;
        cin>>k;
        bool have=binary_search(nums.begin(),nums.end(),k);
        if(!have) cout<<"-1 -1"<<endl;
        else//有钙该元素
        {
            int res1=lower_bound(nums.begin(),nums.end(),k)-nums.begin();
            int res2=upper_bound(nums.begin(),nums.end(),k)-nums.begin()-1;
            cout<<res1<<" "<<res2<<endl;
        }
    }
    return 0;
}

http://www.dtcms.com/a/98343.html

相关文章:

  • 线程概念与控制(中)
  • 深度剖析 ansible:从部署基础到模块运用及剧本编写
  • 【算法day25】 最长有效括号——给你一个只包含 ‘(‘ 和 ‘)‘ 的字符串,找出最长有效(格式正确且连续)括号子串的长度。
  • [Raspberry Pi]如何將看門狗(WatchDog)服務建置在樹莓派的Ubuntu作業系統中?
  • 查看openjdk源码
  • TDengine 中的异常恢复
  • 北斗导航 | 基于因子图优化的GNSS/INS组合导航完好性监测算法研究,附matlab代码
  • pyinstaller 对 pyexecjs模块打包老会有终端框闪烁
  • 【学Rust写CAD】18 定点数2D仿射变换矩阵结构体(MatrixFixedPoint结构别名)
  • 基于深度学习的手势识别系统设计
  • 3. 第三放平台部署deepseek
  • 部署堆叠+链路聚合架构,解锁网络高可用新体验
  • AGV-----RCS基础任务发布
  • 22_js运动函数
  • 历史数据分析——宝钢
  • AI赋能单片机开发的环节与方法
  • 观察者模式:解耦对象间的依赖关系
  • 【嵌入式学习3】多任务编程
  • (二)万字长文解析:deepResearch如何用更长的思考时间换取更高质量的回复?各家产品对比深度详解
  • 锐评|希捷NVMe闪存+磁盘混合存储阵列
  • AB包介绍及导出工具实现+AB包资源简单加载
  • Flutter和React Native在开发app中,哪个对java开发工程师更适合
  • 如何看待职场中的“向上管理”
  • c中的变量命名规则
  • 【精修版】【中项】系统集成项目管理工程师:第12章 项目进度管理-12.4估算活动持续时间
  • Python爬虫:开启数据抓取的奇幻之旅(一)
  • 点云库(Point Cloud Library, PCL)
  • 蓝桥复习 1(Init)
  • TCP网络编程与多进程并发实践
  • STM32_HAL开发环境搭建【Keil(MDK-ARM)、STM32F1xx_DFP、 ST-Link、STM32CubeMX】