折半查找二分查找

简介

折半查找也就是二分查找,也可以叫二分法,本质上都是一样的,通过比对中间值与目标值,一次性就能筛掉一半的数字。

举例:

一个猜数字游戏,让你来猜1-100中我选中的数,如果猜中游戏结束,如果猜的数字比选的数字大,告诉你猜的数大了,反之亦然。

如何针对上述游戏,寻找到一个最快的办法呢?—— 拼运气 或 折半查找

每次猜的数字为区间范围的中数,这样最多在 \log_{2}N 次内一定能找到!

假设选中的数字为 target = 77

第一次:选(1 + 100) / 2 = 50(这里取整数即可)  -> 小了

第二次:选(50 + 100) / 2 = 75  ->  小了

第三次:选(75 + 100) / 2 = 87  ->  大了

第四次:选(75 + 87) / 2 = 81  ->  大了

第五次:选(75 + 81) / 2 = 78  ->  大了

第六次:选(75 + 78) / 2 = 76  ->  小了

第七次:选(76 + 78) / 2 = 77  ->  对了 

通过上述案例,我们能发现,每次在进行查找的时候能够排除一半的错误答案!相当于对所有可能的个数除2。因此折半查找的时间复杂度   \log_{2}N。100个数,最多只要7次就能找到!

虽然折半查找效率这么高,但也是有缺点的~互联网没有“银弹”~

折半查找最大的问题在于,要求你进行查找的数据集必须是有序的!!!所以在编程的时候,可能需要你先进行一次排序~

编码

思路:

1.如果没告诉你数组是有序的,需要对数组进行一次排序(假设是有序的)

2.计算中间数在数组的位置

3.将中间数与目标值进行比对,如果中间数小了,就去右边的区间继续查找,如果中间数大了,就去左边的区间继续查找,如果刚好相等,说明找到了,返回即可。

下述折半查找的代码是基于比区间来写的,一定需要注意!!!否则会导致最终结果不对,这是二分法的细节问题(很容易出错)! 

#include <stdio.h>

int BinarySearch(const int* arr, int target, int size)
{
	int left = 0;
	int right = size - 1;
	
	while (left <= right) //这里定义的是[left, right] 闭区间,一定要注意
	{
        
		//计算中间的那个元素的下标
		int mid = left + (right - left) / 2;
		
		//如果要找的数小于中间的那个数
		if (target < arr[mid])
			right = mid - 1;

		else if (target > arr[mid])
			left = mid + 1;

		//如果找到了就直接返回这个元素的下标
		else
			return mid;
	}
}

int main()
{
	int arr[] = { 5,8,10,23,48,66,88,100 };
	int target = 48;

	//计算数组中元素个数
	int size = sizeof(arr) / sizeof(arr[0]);

	int index = BinarySearch(arr, target, size);
	printf("找到了,这个数在数组中的下标为:%d", index);
	return 0;
}

优化

上述的代码是针对目标值出现在数组的情况,不适用于更普遍一半的情况。在C++标准库中就提供了折半查找这个函数,他的功能是,找到目标值在数组中第一次出现的位置,如果数组中未存在目标值,则找到插入位置。

通过观察上述折半查找算法的过程,我们会发现,

1.如果中间值arr[mid]大于目标值target,则arr[mid+1]~最后 的值都大于目标值taget。arr[left]~arr[mid]可能小于等于目标值target。

2.如果中间值arr[mid]小于目标值target,则arr[left]~arr[mid] 的值都小于目标值target。

最终我们得出,left左边的值都是小于目标值的,right右边的值都是大于目标值的。

如果要找到插入的位置,则找到第一个大于等于目标值的位置。

代码

int searchInsert(int* nums, int numsSize, int target)
{
	int left = 0;
    int right = target - 1;
    while(left <= right)
    {
        int mid = left + (right -left) / 2;
        if(nums[mid] < target)
            left = mid + 1;
        else
            right = mid - 1;
    }
    return left;
}

上述代码,将中间值大于等于的情况进行了合并。为的是找到第一个出现的位置,并且代表的含义也变了——right右边的数是大于等于目标值target的。

举个例子:

int arr[] = {1,2,3,3,3,3,5,6};
target = 3

要去查找第一个3,我们的中间值第一次找到的3是第二个,但我们要找的是第一个,所以需要继续缩小右边界,才能找到。

至于最后为什么返回的是left呢?因为根据代码,left左边的值是小于目标值的,right右边的值是大于等于目标值的,而最终left和right的位置一定是满足right在left的左边且相差一个元素,于是就返回left了。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

EE trade:量化交易需要什么条件才能做

量化交易结合了金融市场知识和计算机科学技术&#xff0c;利用数学和统计模型来进行交易决策。要成功进行量化交易&#xff0c;需要具备以下几个方面的条件&#xff1a; 1. 知识和技能 金融市场知识&#xff1a;需要理解金融市场的基本原理&#xff0c;包括股票、债券、期货、…

学会读书并不简单,如何真正学会读书

一、教程描述 读书是要讲究方法的&#xff0c;否则就会事倍功半&#xff0c;比如&#xff0c;在学习书本上的每一个问题每一章节的时候&#xff0c;首先应当不只看到书面上&#xff0c;而且还要看到书背后的东西&#xff0c;在对书中每一个问题都经过细嚼慢咽&#xff0c;其次…

AI对话聊天软件有哪些?这5款AI软件值得推荐

AI对话聊天软件有哪些&#xff1f;AI对话聊天软件在现代社会中的重要性日益凸显。它们不仅是沟通的工具&#xff0c;更是人们日常生活中的智能助手。通过深度学习和自然语言处理技术&#xff0c;这些软件能够理解我们的意图&#xff0c;提供个性化的建议和服务&#xff0c;让交…

电生明火电火灶是高科技革命还是营销噱头?

电火灶&#xff0c;一个近年来逐渐进入公众视野的新型厨房烹饪设备&#xff0c;凭借其电生明火的独特技术引起了广泛的讨论和关注。然而&#xff0c;关于其是否真正代表高科技革命&#xff0c;还是仅仅是一个营销噱头&#xff0c;外界众说纷纭。今天&#xff0c;我们就来深度解…

在gitlab上发布npm二进制文件

❝ 允许奇迹发生 ❞ 大家好&#xff0c;我是「柒八九」。一个「专注于前端开发技术/Rust及AI应用知识分享」的Coder。 前言 还记得之前我们讲过如何在 npm 上发布二进制文件&#xff1f;吗。我们通过npm将我们之前在Rust 赋能前端-开发一款属于你的前端脚手架中生成Rust二进制文…

进程通信——管道

什么是进程通信&#xff1f; 进程通信是实现进程间传递数据信息的机制。要实现数据信息传递就要进程间共享资源——内存空间。那么是哪块内存空间呢&#xff1f;进程间是相互独立的&#xff0c;一个进程不可能访问其他进程的内存空间&#xff0c;那么这块空间只能由操作系统提…

私有化部署的无忧企业文档,助力企业实现文档权限的精细化管理

在当今数字化快速发展的时代&#xff0c;企业文档管理已成为企业运营中不可或缺的一部分。文档的安全性和访问权限的精确控制对于企业的信息保护至关重要。在无忧企业文档管理系统中&#xff0c;不仅具备强大的内容管理能力&#xff0c;更在权限管理上做到了细致入微。下面我对…

完全背包(类买卖股票问题)

题目传送门——纪念品 题解&#xff1a;这题我一开始以为是简答的那个买卖股票问题&#xff0c;但是做了之后发现并没有那么简单&#xff0c;但是经过思考时候&#xff0c;我发现其和完全背包类问题差不多&#xff0c;怎么说呢&#xff0c;我们首先用p[i][j]去统计每天每种物品…

手写最小的 Agent 系统 — Tiny Agent

调研Agent核心思想&#xff0c;主要有metagpt、React、Reflexion、Toolformer、Swiftsage、Creator等等。Tiny Agent 实现&#xff0c;主要包括 构造大模型、构造工具、构造Agent、运行Agent等步骤。 Agent 核心思想 1. MetaGPT METAGPT: META PROGRAMMING FOR A MULTI-AGEN…

bugku 隐写

说明&#xff1a; 隐写&#xff0c;通过改变图片的大小&#xff0c;即修改了高或者宽&#xff0c;达到隐写flag&#xff0c;要求修改会图片的真实大小找到flag。 1、打开图片 2、使用010editor工具打开图片 通过最下面黄底字的错误提示&#xff0c;表示CRC不匹配&#xff0c;…

如何创建一个Angular项目(超简单)

1、安装Node.js&#xff08;官网Node.js下载&#xff09; 2、运行node -v和npm -v两条命令&#xff08;检验是否下载成功Node.js&#xff09; 3、npm i -g cnpm --registryhttps://registry.npmmirror.com&#xff08;用npm安装cnpm&#xff0c;将镜像源设置为国内镜像源&…

python办公自动化——(三)替换PPT文档中图形数据-折线图

数据替换前 数据替换后 代码实现 # 单折线 pathE:\\13 python 下侧双x轴折线图\\ prs Presentation(path双x轴测试-01.pptx) data_timepd.read_excel(path"数据.xlsx",sheet_name单折线)ppt_9prs.slides…

汽车识别项目

窗口设计 这里的代码放在py文件最前面或者最后面都无所谓 # 创建主窗口 window tk.Tk() window.title("图像目标检测系统") window.geometry(1000x650) # 设置窗口大小# 创建背景画布并使用grid布局管理器 canvas_background tk.Canvas(window, width1000, height…

BugKu 哎,就是玩

说明&#xff1a;通过图片隐写找到迷宫压缩包解码密码&#xff0c;然后通过MG游戏得到井字棋游戏解压密码&#xff0c;最后通过完成井字棋得到flag. 打开实验包&#xff0c;解压后可以看到两个文件。 首先要通过TKR.png找到迷宫.zip的解压密码。 打开图片&#xff0c;发现图片…

二叉树创建和遍历

个人主页 &#xff1a;敲上瘾-CSDN博客二叉树介绍&#xff1a;二叉树(详解)-CSDN博客 目录 一、二叉树的创建 二、二叉树的遍历 1.前序遍历 2.中序遍历 3.后序遍历 4.层序遍历 三、相关计算 1.总节点个数计算 2.叶子节点个数计算 3.深度计算 一、二叉树的创建 关于…

24.6.2(动态开点线段树)

星期一&#xff1a; cf edu round 36 E cf传送门 题意&#xff1a;1到n天初始全为工作日&#xff0c;有两种操作&#xff0c;将 l-r 区间变为 工作日/休息日&#xff0c;每次操作后询问剩余总工作日有多少 思路&…

AIGC绘画设计基础——“这是我学一天AI设计后的作品,效率真的高。”

不少小伙伴都在用Midjourney生成图像作品&#xff0c;但对于完整的设计流程却不太熟悉。今天数艺君就跟大家分享一个干货内容&#xff1a;使用Midjourney设计一个动物IP形象&#xff01; 包含整个项目流程&#xff1a;从项目背景到需求分析&#xff0c;再到出图思路和提示词设计…

Paper Survey——3DGS-SLAM

之前博客对多个3DGS SLAM的工作进行了复现及代码解读 学习笔记之——3DGS-SLAM系列代码解读_gs slam-CSDN博客文章浏览阅读1.9k次&#xff0c;点赞15次&#xff0c;收藏45次。最近对一系列基于3D Gaussian Splatting&#xff08;3DGS&#xff09;SLAM的工作的源码进行了测试与…

竞赛 基于视觉的身份证识别系统

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于机器视觉的身份证识别系统 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f9ff; 更多资料, 项目分享&#xff1a; https://gitee.com/dancheng-sen…

GNeRF论文理解

文章目录 主要解决什么问题&#xff1f;结构设计以及为什么有效果&#xff1f;个人想法。 主要解决什么问题&#xff1f; 本文主要想要解决的问题是 如何使用uncalibrated的照片来进行Nerf重建。虽然说现在已经有了一些方式可以对相机位姿进行估计和优化&#xff0c;但是他们限…