二分查找

二分查找简介

二分查找主要是用于有序序列的二段性的问题的,二段性指的是在数组或其他有序序列中(当然这个有序序列需要我们能够结合题目进行分析出来),某个元素的左边的元素小于它,右边的元素大于它,然后查找进行查找元素

朴素二分查找算法

这个算法的目的就是查找一个有序序列中有没有某个元素,直接查出来就行,就算有多个相同的元素只是需要返回其下标就可以了,不用管其他相同元素的下标

例题

题目链接

二分查找

代码

cpp 复制代码
int search(vector<int>& nums, int target) {
        int left=0,right=nums.size()-1;
        
        while(left<=right)
        {
          //int mid=(left+right)/2;
            int mid=left+(right-left)/2;         //right太大的时候需要与left相
            if(nums[mid]<target)                 //加可能会溢出,所以用下面这种取中点的方式
            {
                left=mid+1;
            }
            else if(nums[mid]>target)
            {
                right=mid-1;
            }
            else return mid;
        }
        return -1;
        
    }

这个可以作为模板来记忆,当然是理解性能记忆,类似的题目条件一换就可以了

求左右端点的二分查找算法

题目链接:在排序数组中查询元素的第一个位置和最后一个位置

因为一个序列中可能存在多个相同的元素,这个序列是非递减的序列,这个题目需要用到求左右端点的二分查找算法

求左端点的二分查找算法

cpp 复制代码
int find_mid(vector<int>& nums, int target)
{
	int left = 0, right = nums.size() - 1;
	while (left < right)
	{
		int mid = left + (right - left) / 2;
		if (target >nums[mid])
		{
			left = mid + 1;
		}
		else
		{
			right = mid;
		}
	}
	if (nums[left] == target)
	{
		return left;
	}
	else
	{
		return -1;
	}
}

大致思路和朴素二分查找算法的思路大差不差,但是有一些细节需要解释,而且非常重要

查找右端点的二分查找算法

cpp 复制代码
int find_mid(vector<int>& nums, int target)
{
	int left = 0, right = nums.size() - 1;
	while (left < right)
	{
		int mid = left + (right - left+1) / 2;
		if (target >=nums[mid])
		{
			left = mid;
		}
		else
		{
			right = mid-1;
		}
	}
	if (nums[left] == target)
	{
		return left;
	}
	else
	{
		return -1;
	}
}

具体分析方法和上面的一样,就不多解释了

题目的代码

cpp 复制代码
vector<int> searchRange(vector<int>& nums, int target) {
        //查询左端点
        if(nums.size()==0) return {-1,-1};
        int left=0,right=nums.size()-1;
        int begin=-1,end=-1;
        while(left<right)
        {
            int mid=left+(right-left)/2;
            if(target<=nums[mid])
            {
                right=mid;
            }
            else
            {
                left=mid+1;
            }
        }
        if(nums[left]==target) begin=left;
        else return {-1,-1};

        //右边端点
        left=0,right=nums.size()-1;
        while(left<right)
        {
            int mid=left+(right-left+1)/2;
            if(target>=nums[mid])
            {
                left=mid;
            }
            else
            {
                right=mid-1;
            }
        }
        end=left;
        return {begin,end};

    }
相关推荐
c++之路14 小时前
C++ 高频易错点
java·jvm·c++
java1234_小锋14 小时前
Spring AI 2.0 开发Java Agent智能体 - 新建 HelloWorld 项目
java·人工智能·spring·spring ai
yue20040314 小时前
Spring IoC 与 DI 核心概念与原理笔记
java·笔记·spring
wuminyu14 小时前
专家视角看Java多态性的底层基石vtable(虚函数表)构建过程解析
java·linux·c语言·jvm·c++
phltxy14 小时前
Spring Cloud 服务注册与发现:Eureka 从原理到实战
java·spring cloud·eureka
生物信息与育种14 小时前
全基因组重测序及群体遗传与进化分析技术服务指南
人工智能·深度学习·算法·数据分析·r语言
测试那点事儿14 小时前
零基础API 接口自动化框架源代码:结构、功能与运行时序
java·servlet·自动化
AI人工智能+电脑小能手14 小时前
【大白话说Java面试题】【Java基础篇】第23题:ConcurrentHashMap的底层原理是什么
java·开发语言·算法·哈希算法·散列表·hash
葳_人生_蕤14 小时前
hot100——回溯和DFS、BFS
算法·深度优先
爱怪笑的小杰杰14 小时前
优化 UniApp 日历组件的多语言切换:告别 setLocale 引起的 App 重启
java·前端·uni-app