【备战蓝桥,冲击省一】 二分查找法 看完你就会了

简介: 【备战蓝桥,冲击省一】 二分查找法 看完你就会了

26b52245c1767966a51d388fb71dba40_watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6ZSh5YWwQ2V5bGFuXw==,size_20,color_FFFFFF,t_70,g_se,x_16.png


一、猜数字


我随便想一个1~100的数字,你的目标是以最小的次数猜到这个数字。你每一次猜测后,我都会说小了、大了或对了。


🌸简单查找


最简单的方法,就是你从1开始依次往上猜,每一次查找只能排除一个数字。


是1吗?                                                                 小了      

1 2 3 ... ... 100


是2吗?                                                                   小了      

1 2 3 ... ... 100



如果我想的数字是99,那么你需要猜99次才能猜到。显而易见的,这是一种很愚蠢的查找方法。


🌸二分查找法


这是一种更好的猜法,第一个数猜50。

 是50吗?                                                                 小了      

1 ... 50 51 ... 100


虽然没有猜中,但是你一下排除了一半的数字!你知道1~50都小了,接下来,你猜75(50和100中间的数)


  是75吗?                                                                         大了      

50 51 50 ... 74 75


大了,剩下的数字又排除了一半!接下来,你猜63(50和75中间的数)。


  是63吗?                                                                      对了      

这就是二分查找法,恭喜你已经学会了!在这个游戏中,每次猜测排除的数字个数如下



不管我心中想到哪个数字,你都可以在7步之内猜到,这就是二分查找法的优点。

二分查找法,每次都能排除一半的数字


我们试一试用代码表示:

#include<stdio.h>
int main()
{
  int l=0,r=100,target;
  scanf("%d",&target);
  while (l < r)
  {
      int mid =(r-l)/2+l;
      if(mid==target)
      {
      printf("你的数字为%d",mid);
      return 0;
    }
      else if (mid>target)
    {
      r=mid-1;
    }      
    else
    {
      l=mid+1;
    }
  }
}



二、二分查找法介绍


🌸固定模板


我们来看一看二分法的固定模板

int binarySearch(vector<int> nums, int left, int right, int x)
{
       int mid;//mid为中点
       while (left<=right)
       {
              mid = left + (right - left) / 2;//取中点
              if (nums[mid] == x) return mid;// 找到x,返回下标
              else if (nums[mid]>x)//中间的数大于x
              {
                    right = mid - 1;//往左子区间[left,mid-1]查找
              }
        else          //中间的数小于x
        {
                    left = mid + 1; //往右子区间[mid+1,right]查找
              }
       }
       return -1;//查找失败,返回-1
}


为什么用【mid = left + (right - left)/2】而不用【mid=(right+left)/2-left】呢?

当left和right都很大的时候,可能会造成越界


我们可以这样理解二分查找法


【left,right】—— 用于标记观察查找范围的位置


【while (left<=right)】—— 只要范围没有缩小到只剩一个元素就继续查找


【 if (nums[mid]>x) 】—— 若中间值大于目标值——【right = mid - 1;】改变右端点,往左子区间[left,mid-1]查找


【 if (nums[mid]<x) 】—— 若中间值小于目标值——【left = mid + 1;】改变左端点,往右子区间[mid+1,right]查找


🌸二分法时间复杂度


一般而言,对于包含n个元素的列表,用简单查找最多需要n步,用二分查找法最多需要log2n步。

二分查找法的运行时间为对数时间,是一种很高效的算法。


三、练习:


🌸力扣704. 二分查找


71f889f72c761c1d499b650e9e3b742e_watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQ2V5bGFuXw==,size_20,color_FFFFFF,t_70,g_se,x_16.png


class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left=0;
        int right=nums.size()-1;
        int a;
        while(left<=right)
        {
            a=(right-left)/2+left;
            if(nums[a]==target)
                return a;
            else if(nums[a]>target)
                right=a-1;
            else
                left=a+1; 
        }
    return -1;
    }
};


🌸力扣35. 搜索插入位置


ebbea002594c95e8a420ba7fbfb053bc_watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQ2V5bGFuXw==,size_20,color_FFFFFF,t_70,g_se,x_16.png

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int n = nums.size();
        int l=0,r=n-1;
        while(l<=r){
            int mid=l+(r-l)/2;
            if(nums[mid]<target)
                l=mid+1;
            else r=mid-1;
        }
        return l;
    }
};


🌸力扣167. 两数之和 II - 输入有序数组


3baba3d3f8b6a06305ccf294a38bdc73_watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQ2V5bGFuXw==,size_20,color_FFFFFF,t_70,g_se,x_16.png

class Solution {
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
        for(int i=0;i<numbers.size();i++)
        {
            int left=i+1,right=numbers.size()-1;
            while(left<=right)
            {
                int mid=(right-left)/2+left;
                if(numbers[i]+numbers[mid]==target)
                {
                     return {i+1,mid+1};
                }
                else if(numbers[i]+numbers[mid]>target)
                {
                    right=mid-1;
                }
                else
                {
                    left=mid+1;
                }
            }
        }
        return {-1, -1};
    }
};

相关文章
|
10月前
|
缓存 算法 安全
惊险!备战3个月,五面蚂蚁金服差点倒在最后一面
作为程序员,免不了要经历面试这关,虽然平时工作勤勤恳恳,但是面试上面未必能展示的出来,比如平时都是做增删改查的业务系统,面试官非要问你如何处理高并发大数据,本来是写java代码,非要问你大型网站架构,这些问题防不胜防,本文就自己一次在蚂蚁金服的面试经验来总结一下,抛砖引玉。
|
10月前
|
存储 算法
【备战蓝桥,冲击省一】高精度算法实现加减乘除
【备战蓝桥,冲击省一】高精度算法实现加减乘除
124 0
|
10月前
|
算法
【备战蓝桥,冲击省一】 进制转换 你不会还不会吧?
【备战蓝桥,冲击省一】 进制转换 你不会还不会吧?
87 0
|
10月前
【备战蓝桥,冲击省一】-- 日期问题
【备战蓝桥,冲击省一】-- 日期问题
67 0
|
10月前
|
存储 人工智能 算法
【2021年蓝桥省赛真题】赛前最后冲刺,省一我来啦
【2021年蓝桥省赛真题】赛前最后冲刺,省一我来啦
259 0
|
人工智能
牛客 城市网络(倍增 思维)
牛客 城市网络(倍增 思维)
52 0
牛客 城市网络(倍增 思维)
|
人工智能 算法
[leetcode] 适合打劫银行的日子 -前缀和
前缀和思想 用数组 l[ ]表示前面有多少个数满足 a[i−1]>=a[i] 用数组 r[] 表示前面有多少个数满足 a[i]<=a[i+1] O(n)遍历之后得到 l[] , r[] 然后O(n)找满足l [ i ] > = t i m e & & r [ i ] > = t i m e 的下标存入 vector 并返回
64 0
[leetcode] 适合打劫银行的日子 -前缀和
|
算法 大数据 API
【蓝桥真题3】蓝桥改革变难,想进国赛这些能力你可缺一不可(中)
【蓝桥真题3】蓝桥改革变难,想进国赛这些能力你可缺一不可
172 0
【蓝桥真题3】蓝桥改革变难,想进国赛这些能力你可缺一不可(下)
【蓝桥真题3】蓝桥改革变难,想进国赛这些能力你可缺一不可
199 0
【蓝桥真题3】蓝桥改革变难,想进国赛这些能力你可缺一不可(下)
|
Java
【蓝桥真题3】蓝桥改革变难,想进国赛这些能力你可缺一不可(上)
【蓝桥真题3】蓝桥改革变难,想进国赛这些能力你可缺一不可
153 0