二分查找算法(1) _二分查找_模板

news2024/9/21 21:49:59

个人主页:C++忠实粉丝
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C++忠实粉丝 原创

二分查找算法(1) _二分查找模板

收录于专栏【经典算法练习
本专栏旨在分享学习算法的一点学习笔记,欢迎大家在评论区交流讨论💌

1. 二分查找算法简介

二分查找是一种在已排序数组中高效查找目标值的算法。其核心思想是通过不断将查找范围分成两部分,利用中间元素与目标值的比较来缩小范围。具体步骤如下:

1. 初始设定:设定两个指针,分别指向数组的起始和结束位置。
2. 计算中间位置:计算中间索引,并与目标值进行比较。
3. 比较结果:
        如果中间元素等于目标值,查找成功。
        如果目标值小于中间元素,调整结束指针,缩小到左半部分。
        如果目标值大于中间元素,调整起始指针,缩小到右半部分。
4. 重复:重复上述步骤,直到找到目标值或范围为空。
这种方法的时间复杂度为O(log n),使其在大数据集中非常高效。

2. 题目链接:

OJ链接:二分查找

3. 题目描述 :

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1
示例 1:

输入: nums = [-1,0,3,5,9,12], target = 9输出: 4
解释: 9 出现在 nums中并且下标为 4

示例 2:

输入: nums= [-1,0,3,5,9,12], target= 2输出: -1
解释: 2 不存在 nums中因此返回 -1

提示:

  1. 你可以假设 nums 中的所有元素是不重复的。
  2. n 将在 [1, 10000]之间。
  3. nums 的每个元素都将在 [-9999, 9999]之间。

注意:

我们这道题的二分查找中的数据都是不重复的且有序 

4. 解法 :

    解法一:暴力枚举遍历:

    算法思路 :

遍历整个数组寻找target

    代码展示 :

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int ret = -1;
        auto i = nums.begin();
        for(i = nums.begin(); i < nums.end(); i++)
            if(*i == target) ret = i - nums.begin();
        return ret;
    }
};

 

    结果分析 :

用vector的迭代器直接遍历整个数组,我们的时间复杂度为O(N) 

    对暴力算法的反思与优化 :

我们的暴力算法虽然容易想,但是时间复杂度不是很好,而且我们的暴力算法完全没有利用题目中数组是有序的这一个条件,所以我们可以进一步优化.

 

这里假设我们先从4开始查找,假设我们的target比4大,那4的左边不就都可以舍去吗?这不就让我们简化了一些不必要的遍历吗? 

    解法二: 二分查找 :

    算法思路 :

a.定义 left , right 指针,分别指向数组的左右区间。
b.找到待查找区间的中间点 mid ,找到之后分三种情况讨论:
        i.arr[mid] == target 说明正好找到,返回 mid 的值;
        ii.arr[mid] > target 说明[mid, right] 这段区间都是⼤于 target 的,因此舍
去右边区间,在左边[left, mid - 1] 的区间继续查找,即让 right = mid -
1 ,然后重复 2 过程;
        iii.arr[mid] < target 说明[left, mid] 这段区间的值都是⼩于 target 的,因
    此舍去左边区间,在右边[mid + 1, right] 区间继续查找,即让 left = mid +
    1 ,然后重复 2 过程;
c.当 left 与 right 错开时,说明整个区间都没有这个数,返回 - 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) right = mid - 1;
            else if(nums[mid] < target) left = mid + 1;
            else return mid;
        }
        return -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) / 3;
            if(nums[mid] > target) right = mid - 1;
            else if(nums[mid] < target) left = mid + 1;
            else return mid;
        }
        return -1;
    }
};

 

    结果分析 :

二分查找时间复杂度分析:   

 二分查找的时间复杂度可以通过分析其每一步操作来证明。具体分析如下:

    初始条件:二分查找在一个已排序的数组中进行搜索,假设数组长度为n

    每次操作:在每一次迭代中,算法都会计算中间索引 mid,并根据与目标值的比较来决定下一步搜索的范围。每次迭代都将当前搜索范围减半。

    减半过程:

    首先,搜索的范围是n(整个数组)。
    第一次迭代后,范围缩小到n / 2。
    第二次迭代后,范围缩小到n / 4。
    第三次迭代后,范围缩小到n / 8。
    ...
    这个过程会一直持续,直到范围缩小到 1。
    结束条件:当搜索范围缩小到 0(即 left > right)时,算法结束。每次迭代都将问题规模减半,因此我们可以得到以下关系:

        n, n/2, n/4, n/8, ......, 1;

    数学推导:设迭代次数为k,那么在第k 次迭代时,范围大小为:

        n/2^k = 1

    解这个方程,可以得到:

        n = 2^k ----> k = log2(n)

    时间复杂度:因此,二分查找的时间复杂度是O(logn),因为它的迭代次数与输入规模的对数成正比。

    总结:二分查找在每一步中通过将搜索范围减半,有效地减少了需要检查的元素数量,因此其时间复杂度为O(logn)。

5. 二分算法模板总结

while(left <= right)
{
	int mid = left + (right - left) / 2;
	if (....)
		left = mid + 1;
	else if (....)
		right = mid - 1;
	else
		return ...;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2153396.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

掌握Android开发新趋势:Jetpack与现代架构技术全解析

随着Android开发技术的不断进步&#xff0c;Jetpack和现代架构技术已成为构建高效、可维护应用的关键。本文将为您介绍一套全面的学习资料&#xff0c;包括大纲、PDF文档、源代码以及学习视频&#xff0c;帮助您深入理解Jetpack核心库、架构组件以及现代开发工具。 内容&#…

linux-基础知识4

网络连接性测试 ping ping可以用来测试本机与目标主机的连通速度网络稳定性 ping -c 5 -s 1024 目标主机ip地址 -c 表示ping包的个数,linux如果缺省-c会一直ping下去&#xff0c;windows平台的选项是-n -s指定ping发送数据的字节数默认是84字节。windows的是-l 没有问题时会之…

如何设计出一个比较全面的测试用例

目录 1. 测试用例的基本要素(不需要执行结果) 2. 测试用例的给我们带来的好处 3. 用例编写步骤 4. 设计测试用例的方法 4.1 基于需求进行测试用例的设计 4.2 具体的设计方法 1.等价类 2.边界值 3.判定表&#xff08;因果图&#xff09; 4.正交表法 5.场景设计法 6.错误猜测…

IO流体系(FiletOutputStream)

书写步骤&#xff1a; 1.创建字节输出流对象 细节1:参数是字符串表示的路径或者是File对象都是可以的 细节2:如果文件不存在会创建一个新的文件&#xff0c;但是要保证父级路径是存在的。 细节3:如果文件已经存在&#xff0c;则会清空文件 2.写数据 细节:write方法的参数…

Python | 绘制核密度图

写在前面 台风天&#xff0c;适合敲代码。前两天正好看到一个有意思的核密度图&#xff0c;使用的是seaborn绘制的。之前了解过这个包&#xff0c;但是一致没有去绘制相关的图&#xff0c;这次正好去学习一下相关的函数。 绘制结果如下所示&#xff1a; 主要两个有意思的地方…

二维光场分析

一、单色光波长的复振幅表示 实波函数 复波函数 复振幅 由于时间因子相同,可以用复振幅来描述 光强 1.1 球面波的复振幅(单色点光源发出的光波) 等相位面是同心球面,波矢处处与等相位面垂直,即 是 r = 1 处的振幅 发散球面波: 会聚球面波: <

828华为云征文 | 华为云X实例监控与告警管理详解

前言 随着云计算的飞速发展&#xff0c;越来越多的企业将业务部署在云平台上&#xff0c;云服务器实例的管理变得尤为重要。云实例的稳定性、性能及安全性&#xff0c;直接影响着业务的连续性与用户体验。为了确保这些目标的实现&#xff0c;监控与告警是关键手段。本文将详细…

2024华为杯研赛C题原创python代码+结果表(1-2问)|全部可运行|精美可视化

2024华为杯研赛C题原创python代码结果表&#xff08;1-2问&#xff09;&#xff5c;全部可运行&#xff5c;精美可视化 以下均为python代码&#xff0c;推荐用anaconda中的notebook当作编译环境 第一问&#xff1a; import pandas as pd import numpy as np import matplotl…

pg入门18—如何使用pg gis

1. 下载postgre gis镜像 2. 运行镜像 docker run -p 15432:5432 -d -e POSTGRES_PASSWORDAb123456! postgis/postgis:12-3.4-alpine 3. 使用gis # 进入容器&#xff0c;登录pgdocker exec -it bash# 登录数据库psql -U postgres# 创建数据库CREATE DATABASE mygeotest;# 使用…

初步认识C++模版

前言 在C语言中&#xff0c;我们知道函数的形参需要指定类型&#xff0c;但是在C中&#xff0c;我们可以模版实现各种类型参数的通用函数。 1. 泛型编程 我们通过函数重载实现多种类型的同一作用的函数。如交换函数&#xff1a; void Swap(int& left, int& right) …

力扣 167.两数之和||—输入为有序数组

文章目录 题目介绍解法 题目介绍 解法 利用相向双指针&#xff0c;初始时l在最用左边&#xff0c;r在最右边 1.numbers[l] numbers[r] < target 则 l 2.numbers[l] numbers[r] < target 则 r 3.numbers[l] numbers[r] target 说明找到了答案 class Solution {publi…

linux 操作系统下dhcrelay命令介绍和案例应用

linux 操作系统下dhcrelay命令介绍和案例应用 dhcrelay是一个用于DHCP&#xff08;动态主机配置协议&#xff09;中继的命令&#xff0c;主要功能是在没有本地DHCP服务器的子网中转发DHCP请求。这使得不同子网的DHCP客户端能够与位于其他子网中的DHCP服务器进行通信。 dhcrela…

基于YOLO算法的网球运动实时分析-击球速度测量-击球次数(附源码)

这个项目通过分析视频中的网球运动员来测量他们的速度、击球速度以及击球次数。该项目使用YOLO&#xff08;You Only Look Once&#xff09;算法来检测球员和网球&#xff0c;并利用卷积神经网络&#xff08;CNNs&#xff09;来提取球场的关键点。此实战项目非常适合提升您的机…

面向对象开发流程例题

答案;C 知识点 面向对象分析 认定对象 组织对象 对象间的相互作用 基于对象的操作 面向对象设计 识别类及对象 定义属性 定义服务 识别关系 识别包 面向对象程序设计 程序设计范型 选择一种OOPL 面向对象测试 算法层 类层 模板层 系统层

发布Java项目到Maven中央仓库

1.背景 本教程为2024年9月最新版 我有一个Java项目&#xff0c;想发布到Maven中央仓库&#xff0c;任何人都可以在pom文件中引用我的代码 引用格式如下&#xff08;以rocketmq为例&#xff09;&#xff1a; <dependency><groupId>org.apache.rocketmq</groupId…

鸿蒙开发之ArkUI 界面篇 十七 购物综合案例

layoutWeight:子元素与兄弟元素主轴方向按照权重进行分配,参数是联合类型&#xff0c;数字或者是字符串&#xff0c;在指定的空间占多少份额&#xff0c;数字越大&#xff0c;表示在空间中占用的份额越多&#xff0c;如果父容器的子组件没有别的指定&#xff0c;剩下的空间全部…

LeetCode[中等] 438. 找到字符串中所有字母异位词

给定两个字符串 s 和 p&#xff0c;找到 s 中所有 p 的 异位词 的子串&#xff0c;返回这些子串的起始索引。不考虑答案输出的顺序。 异位词 指由相同字母重排列形成的字符串&#xff08;包括相同的字符串&#xff09;。 思路&#xff1a;滑动窗口 s包含p的异位词 ——> 则…

如何导入一个Vue并成功运行

注意1&#xff1a;要确保自己已经成功创建了一个Vue项目&#xff0c;创建项目教程在如何创建Vue项目 注意2&#xff1a;以下操作均在VS Code&#xff0c;教程在VS Code安装教程 一、Vue项目导入VS Code 1.点击文件&#xff0c;然后点击将文件添加到工作区 2. 选择自己的vue项…

Java 每日一刊(第13期):this super static

“优秀的代码不仅仅是给机器看的&#xff0c;更是给人看的。” 前言 这里是分享 Java 相关内容的专刊&#xff0c;每日一更。 本期将为大家带来以下内容&#xff1a; this 关键字super 关键字static 关键字 this 关键字 this 关键字是 Java 中最常见的关键字之一&#xf…

数据中台系统产品原型RP原型Axure高保真交互原型 源文件分享

在数字化时代&#xff0c;数据已经成为企业最宝贵的资产之一。为了更好地管理和利用这些数据&#xff0c;这边为大家整理了一套数据中台Axure高保真原型。这套原型致力于为企业提供全方位的数据服务&#xff0c;助力企业实现数据驱动的创新发展。 下载及预览地址&#xff1a;h…