【算法】对二分搜索的理解

二分搜索大家都很熟悉,首先我们先来看看基本框架

func binarySearch(nums []int, target int) int {left, right := 0, ...for ... {mid := left + (right-left)/2if nums[mid] == target {...} else if nums[mid] < target {left = ...} else if nums[mid] > target {right = ...}}return ...
}

看完代码之后我们会发现:

  1. 数组得是有序的才能成立
  2. 在存在两个及以上的答案时,只能找出一个,至于下标的情况我觉得可以自定义
  3. 如果数组长度为偶数,初始化时mid在中间偏左的那一格

接下来在实战中看:

寻找一个数

这可以说是最简单的内容

func binarySearch(nums []int, target int) int {left := 0 //right := len(nums) - 1 for left <= right {mid := left + (right - left) / 2 if nums[mid] == target { return mid} else if nums[mid] < target { left = mid + 1 // [mid + 1, right]} else if nums[mid] > target { // 目标值在左半部分,注意right = mid - 1 // [left, mid - 1]}}return -1 // 未找到
}

这里需要注意一点,为何是 for left <= right 而不是 for left < right

我们可以先从最极端的情况入手,假设要寻找的数在最后一个,那么在前一步应该是 left = right - 1, mid = left ,然后 left = mid + 1 = right,在进行循环时,循环就会进不去。

从理论上解释,因为在之前设定值时,数组为闭区间 [left, right] ,所以得保证边界值,也就是说,循环的条件设定和搜索区间设定是相关联的

寻找左侧边界

那么接下来看一下右侧开区间的做法:

func leftBound(nums []int, target int) int {left := 0right := len(nums)for left < right {mid := left + (right - left) / 2if nums[mid] == target {right = mid} else if nums[mid] < target {left = mid + 1 // [mid + 1, right)} else if nums[mid] > target {right = mid // [left, mid)}}return left
}

不难发现,随着区间的修改,在对应条件下的操作也会对应转换。

在这里阐述一点我的个人想法,二分查找的最大特点在于区间设定,而在对应条件下做出的操作有点像递归,基本盘并没有改变

寻找右侧边界

func right_bound(nums []int, target int) int {left, right := 0, len(nums)for left < right {mid := left + (right-left)/2if nums[mid] == target {   left = mid + 1        } else if nums[mid] < target {left = mid + 1} else if nums[mid] > target {right = mid}}return left - 1  
}

这里面的精华在于

if nums[mid] == target {   left = mid + 1 

他并没有直接的收网,而是继续直到最右侧的诞生,这也得益于mid的设置,可以把他看成以left为基准向前进

实战

我们来看力扣的34. 在排序数组中查找元素的第一个和最后一个位置

直接把方法摆上既可以解决

func searchRange(nums []int, target int) []int {left := leftBound(nums, target)right := rightBound(nums, target)return []int{left, right}
}func leftBound(nums []int, target int) int {left, right := 0, len(nums)-1for left <= right {mid := left + (right - left) / 2if nums[mid] < target {left = mid + 1} else if nums[mid] > target {right = mid - 1} else if nums[mid] == target {// 别返回,锁定左侧边界right = mid - 1}}// 判断 target 是否存在于 nums 中if left < 0 || left >= len(nums) {return -1}// 判断一下 nums[left] 是不是 targetif nums[left] == target {return left}return -1
}func rightBound(nums []int, target int) int {left, right := 0, len(nums)-1for left <= right {mid := left + (right - left) / 2if nums[mid] < target {left = mid + 1} else if nums[mid] > target {right = mid - 1} else if nums[mid] == target {// 别返回,锁定右侧边界left = mid + 1}}// 判断 target 是否存在于 nums 中// if left - 1 < 0 || left - 1 >= len(nums) {//     return -1// }if right < 0 || right >= len(nums) {return -1}if nums[right] == target {return right}return -1
}

当然也有另外一种解法,力扣显示这种时间复杂度更低
在这里插入图片描述

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

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

相关文章

圈子社交系统:打破时间与空间的限制。APP小程序H5三端源码交付,支持二开!

在现代社会&#xff0c;社交已成为人们生活中不可或缺的一部分。然而&#xff0c;传统的社交方式往往受制于时间和空间的限制&#xff0c;使得人们难以充分发挥社交的潜力。为了解决这一问题&#xff0c;圈子社交系统应运而生。 圈子社交系统通过技术手段打破时间与空间的限制&…

Linux环境搭建SVN服务器并结合内网穿透实现远程访问

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;网络奇遇记、Cpolar杂谈 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. Ubuntu安装SVN服务二. 修改配置文件2.1 修改svnserve.conf文件2.2 修改pass…

【Linux】cp 命令使用

cp 命令 cp&#xff08;英文全拼&#xff1a;copy file&#xff09;命令主要用于复制文件或目录。 著者 由Torbjorn Granlund、David MacKenzie和Jim Meyering撰写。 语法 cp [选项]... [-T] 源文件 目标文件或&#xff1a;cp [选项]... 源文件... 目录或&#xff1a;cp [选…

synchronized关键字-监视器锁(monitor lock)

这就是我们上一篇中代码提到的加锁的主要方式,本质上是调用系统api进行加锁,系统api本质是靠cpu特定指令加锁. synchronize的特性 互斥性 synchronized会起到互斥效果,某个线程执行到某个对象的synchronized中时,,其它线程如果也执行到同一个对象synchronized就会阻塞等待(锁…

【已解决】pycharm使用pandas导入numpy报错“Original error”

程序中使用pandas进行表格文件处理时&#xff0c;报错了numpy的导入失败问题&#xff0c;错误提示是这样的 Traceback (most recent call last):File "D:/pandastest.py", line 1, in <module>import pandas as pdFile "E:\Python\Python38\lib\site-pac…

Python实现FA萤火虫优化算法优化卷积神经网络回归模型(CNN回归算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 萤火虫算法&#xff08;Fire-fly algorithm&#xff0c;FA&#xff09;由剑桥大学Yang于2009年提出 , …

请介绍一下MySQL的存储引擎及其特点

问题&#xff1a;请介绍一下MySQL的存储引擎及其特点。 回答&#xff1a; MySQL是一个开源的关系型数据库管理系统&#xff0c;它支持多种存储引擎&#xff0c;每个存储引擎都有其自身的特点和适用场景。下面是对MySQL常见存储引擎的简要介绍&#xff1a; InnoDB&#xff1a; …

小航助学题库白名单竞赛考级蓝桥杯等考scratch(8级)(含题库教师学生账号)

需要在线模拟训练的题库账号请点击 小航助学编程在线模拟试卷系统&#xff08;含题库答题软件账号&#xff09; 需要在线模拟训练的题库账号请点击 小航助学编程在线模拟试卷系统&#xff08;含题库答题软件账号&#xff09;

大模型训练的过程(通俗易懂)

模型训练的过程是什么样的&#xff1f; 模型训练的过程就像是教一个小孩子去认识这个世界&#xff0c;让他从经验中学习和逐步提高。 数据预处理&#xff1a;这就像是给小孩子提供学习的教材。首先&#xff0c;我们需要将原始的文本数据&#xff08;原始的故事、课本等&#x…

Java核心知识点整理大全26-笔记

目录 27. Storm 7.1.1. 概念 27.1.1. 集群架构 27.1.1.1. Nimbus&#xff08;master-代码分发给 Supervisor&#xff09; 27.1.1.2. Supervisor&#xff08;slave-管理 Worker 进程的启动和终止&#xff09; 27.1.1.3. Worker&#xff08;具体处理组件逻辑的进程&#xff…

力扣二叉树--第三十九天

前言 本来打算这几天不写题了&#xff0c;等待是痛苦的&#xff0c;复习完了就写写题吧&#xff0c;等待考试多焦虑啊。 内容 一、二叉树的最近公共祖先 236. 二叉树的最近公共祖先 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 递归 func lowestCommonAnces…

【Java GUI窗体开发实践】基于抽象模板模式设计GUI

文章目录 前言一、抽象模板模式二、使用步骤1.定义模板抽象类2.子类继承父类,重写父类方法前言 尽管Java GUI 是一项比较古老的技术,但是可以在Java GUI中训练设计模式,让自己的代码书写更加规范。 不管是Java GUI项目还是其他项目,我们都希望代码有较强的可维护性和健壮性…

代洋集团:引领太阳能储能电站新时代

代洋集团&#xff0c;一直致力于绿色能源领域的领导者&#xff0c;再创太阳能储能电站新高度。我们精心打造的太阳能储能电站&#xff0c;将高效光伏板与智能储能系统完美结合&#xff0c;提供稳定、持续的清洁能源。 此款太阳能储能电站&#xff0c;采用最先进的光电技术&…

c 语言常用的加密算法——AES加密算法

在C语言中&#xff0c;常用的加密算法包括以下几种&#xff1a; AES加密算法&#xff1a;这是一种对称加密算法&#xff0c;广泛用于数据加密。在C语言中&#xff0c;可以使用openssl库来实现AES加密。RSA加密算法&#xff1a;这是一种非对称加密算法&#xff0c;即加密和解密…

Mysql timestamp和datetime区别

文章目录 一、存储范围和精度二、默认值和自动更新三、时区处理四、索引和性能五、存储空间和数据复制六、使用场景和注意事项七、时区转换 MySQL是一个常用的关系型数据库管理系统&#xff0c;其内置了多种数据类型用于存储和操作数据。其中&#xff0c;timestamp和datetime是…

分包(微信小程序)

首先&#xff0c;微信小程序中使用分包是为了减少首屏的请求&#xff0c;因为微信小程序会默认下载主包内的内容并展示到页面上&#xff0c;但是随着业务量的增加&#xff0c;代码量也会越来越大。会导致我们启动小程序的时候首页加载速度过慢的这个问题。这时我们就可以采用分…

C语言-字符串函数

字符串 1. 字符串处理函数 1. strlen&#xff1a;长度 作用&#xff1a;测量字符串长度 语法&#xff1a; size_t strlen(const char *s);参数&#xff1a; s&#xff1a;要测量的字符指针变量 返回值&#xff1a; 字符串长度 注意&#xff1a;不包含 ‘\0’ sizeof 是个关…

研习代码 day49 | 动态规划——子序列问题(回文)

一、回文子串&#xff08;连续&#xff09; 1.1 题目 给你一个字符串 s &#xff0c;请你统计并返回这个字符串中 回文子串 的数目。 回文字符串 是正着读和倒过来读一样的字符串。 子字符串 是字符串中的由连续字符组成的一个序列。 具有不同开始位置或结束位置的子串&#xf…

解决(error) ERR Errors trying to SHUTDOWN. Check logs.问题~

该问题出现在我在使用shutdown关闭redis服务器时&#xff0c;出现该问题的原因是由于配置文件的日志文件位置未配置或者缺少日志文件 我自己出现该问题是因为缺少日志文件&#xff0c;解决步骤如下所示&#xff1a; 第一步&#xff1a;在该目录下使用touch命令创建日志文件 第…

【工具与中间件】快速构建飞书群聊机器人

文章目录 0. 前言1. 无痛入门1.1 飞书创建群聊机器人1.2 Webhook 请求示例1.3 设置安全策略 2. 实战3. 总结3.1 使用体验3.2 深入使用建议 先进团队用飞书&#xff0c;先进飞书群聊有...... 0. 前言 科技蓬勃发展的今天&#xff0c;我们可以轻松拥有属于自己/团队的机器人。日…