算法思想总结:二分查找算法

news/2024/7/7 19:38:57

                                             创作不易,感谢三连!! 

一、二分查找算法思路总结

大家先看总结,然后再根据后面的题型去慢慢领悟

二、二分查找(easy)

. - 力扣(LeetCode)二分查找

思路:(模版1)正常的二分查找策略

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

三、在排序数组中查找元素的第一个位置和最后一个位置

. - 力扣(LeetCode)在排序数组中查找元素的第一个位置和最后一个位置

 要注意示例3提到的边界情况!!

思路:找第一个,用左区间端点查找(模版2),找最后一个,用右端点区间查找(模版3)

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target)
    {
        if(nums.size()==0)  return {-1,-1};//处理边界情况,否则会越界
        int begin=0;
        //区间左端点
           int left=0,right=nums.size()-1;
           while(left<right)
          {
            int mid=left+(right-left)/2;
            if(nums[mid]<target) left=mid+1;
            else right=mid;//最后会落在区间的左端点
          }
          if(nums[left]!=target) return{-1,-1};//找不到
          else begin=left;
        //区间右端点
          right=nums.size()-1;
           while(left<right)
          {
            int mid=left+(right-left+1)/2;
            if(nums[mid]<=target) left=mid;//最后会落在区间的右端点
            else right=mid-1;
          }
        return {begin,right};//此时至少有一个左端点,所以不可能找不到。
    }
};

四、x的平方根

 . - 力扣(LeetCode)x的平方根

思路:右端区间二分查找法

class Solution {
public:
    int mySqrt(int x) 
    {
        if(x<1) return 0;//处理边界情况
        int left=1,right=x/2;
        while(left<right)
        {
            long long mid=left+(right-left+1)/2;
            if(mid*mid>x) right=mid-1;
            else  left=mid;
        }
        return left;
    }
};

 五、搜索插入位置

. - 力扣(LeetCode)搜索插入位置

思路1:左端区间查找 

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

思路2:右端区间查找(有特殊情况,比如正好是和targe相等且只有一个元素

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) 
    {
        int left=0,right=nums.size()-1;
        while(left<right)
        {
            int mid=left+(right-left+1)/2;
            if(nums[mid]<target) left=mid;
            else right=mid-1;
        }
        //右端区间要考虑边界情况(特殊情况,只有一个元素且正好等于target)
        if(nums[left]>=target) return left;
        return left+1;
    }
};

 六、山峰数组峰顶的索引

 . - 力扣(LeetCode)山峰数组峰顶的索引

本题特别的就是不再是升序,而是去找二段性的规律

思路1:左端区间查找 

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

思路2:右端区间查找 

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

七、寻找峰值

. - 力扣(LeetCode)寻找峰值

 左区间端点法:

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

右区间端点法:

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

 八、点名

. - 力扣(LeetCode)点名

左区间端点法 

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

注意:插入元素的时候要注意是否是在最右边插入!

九、 寻找旋转数组中的最小值

. - 力扣(LeetCode)寻找旋转数组中的最小值

思路:左区间端点查找法

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

十、二分查找规律的再总结

       二分查找的策略基本上都是去找一个数,对应的有三种模版:正常的二分查找、左区间端点查找、右区间端点查找。其中正常的二分查找局限性比较大,必须得是升序且限制条件较多,大多数情况下不符合题意。最常用的就是左区间端点(关键是left会大跳跃,且目标位置在较大值区间的左边)和右区间端点法(关键是right会大跳跃,且目标位置在较小值区间的右边)。

  

     后面有遇到相关oj题博主会继续更新的……感谢支持!!


http://lihuaxi.xjx100.cn/news/2093121.html

相关文章

一篇文章读懂LangChain

在日常生活中&#xff0c;我们通常致力于构建端到端的应用程序。有许多自动机器学习平台和持续集成/持续交付&#xff08;CI/CD&#xff09;流水线可用于自动化我们的机器学习流程。我们还有像 Roboflow 和 Andrew N.G. 的 Landing AI 这样的工具&#xff0c;可以自动化或创建端…

【python】使用代理IP爬取猫眼电影专业评分数据

前言 我们为什么需要使用IP代理服务&#xff1f; 在编写爬虫程序的过程中&#xff0c;IP封锁无疑是一个常见且棘手的问题。尽管网络上存在大量的免费IP代理网站&#xff0c;但其质量往往参差不齐&#xff0c;令人堪忧。许多代理IP的延迟过高&#xff0c;严重影响了爬虫的工作…

带你吃透 Vue3 中 侦听器 【watch ,watchEffect】数据监听的使用及注意事项

目录 watch概述详细信息使用场景一&#xff1a;使用场景二&#xff1a;使用场景三&#xff1a;使用场景四&#xff1a;使用场景五&#xff1a;配置参数说明 watchEffect()详细信息 watch 对比 watchEffect 的区别停止侦听器 前提摘要&#xff1a; 本文是在基于 Vue3 的&#xf…

力扣106 从中序与后续遍历序列构造二叉树

文章目录 题目描述解题思路代码 题目描述 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 示例 1: 输入&#xff1a;inorder [9,3,15,20,7], …

【论文笔记合集】ARIMA 非平稳过程通过差分转化为平稳过程

本文作者&#xff1a; slience_me 文章目录 ARIMA 非平稳过程通过差分转化为平稳过程文章原文具体解释详解 ARIMA 非平稳过程通过差分转化为平稳过程 文章原文 Many time series forecasting methods start from the classic tools [38, 10]. ARIMA [7, 6] tackles the foreca…

C++提高笔记(三)---STL容器(vector、deque)

1、vector容器 1.1vector基本概念 功能&#xff1a;vector数据结构和数组非常相似&#xff0c;也称为单端数组 vector与普通数组区别&#xff1a;不同之处在于数组是静态空间&#xff0c;而vector可以动态扩展 动态扩展&#xff1a;并不是在原空间之后续接新空间&#xff0…

Lucene 分词 示例代码

import org.apache.lucene.analysis.tokenattributes.CharTermAttribute; import org.apache.lucene.analysis.TokenStream; import org

C++作业day3

设计一个Per类&#xff0c;类中包含私有成员:姓名、年龄、指针成员身高、体重&#xff0c;再设计一个Stu类&#xff0c;类中包含私有成员:成绩、Per类对象p1&#xff0c;设计这两个类的构造函数、析构函数和拷贝构造函数。 #include <iostream>using namespace std;//定义…