代码随想录二刷复习(二分法)

news/2024/11/10 12:10:56/文章来源:https://www.cnblogs.com/bathwind/p/18308405

二分法模板:

1:左闭右闭区间写法

第一种写法,我们定义 target 是在一个在左闭右闭的区间里,也就是[left, right] (这个很重要非常重要)。

区间的定义这就决定了二分法的代码应该如何写,因为定义target在[left, right]区间,所以有如下两点:

while (left <= right) 要使用 <= ,因为left == right是有意义的,所以使用 <=
if (nums[middle] > target) right 要赋值为 middle - 1,因为当前这个nums[middle]一定不是target,那么接下来要查找的左区间结束下标位置就是 middle - 1

点击查看代码
class Solution:def search(self, nums: List[int], target: int) -> int:left = 0right = len(nums) - 1while left <= right:mid = (left + right)//2if(target > nums[mid]):left = mid + 1if(target == nums[mid]):return midif(target < nums[mid]):right = mid - 1return -1

2:左闭右开

有如下两点:

while (left < right),这里使用 < ,因为left == right在区间[left, right)是没有意义的
if (nums[middle] > target) right 更新为 middle,因为当前nums[middle]不等于target,去左区间继续寻找,而寻找区间是左闭右开区间,所以right更新为middle,即:下一个查询区间不会去比较nums[middle]

点击查看代码
class Solution:def search(self, nums: List[int], target: int) -> int:left, right = 0, len(nums)  # 定义target在左闭右开的区间里,即:[left, right)while left < right:  # 因为left == right的时候,在[left, right)是无效的空间,所以使用 <middle = left + (right - left) // 2if nums[middle] > target:right = middle  # target 在左区间,在[left, middle)中elif nums[middle] < target:left = middle + 1  # target 在右区间,在[middle + 1, right)中else:return middle  # 数组中找到目标值,直接返回下标return -1  # 未找到目标值
下面来看二分法代码随想录中的题目:

leetcode 35

在这里插入图片描述
题目给出了排序数组,很大概率就是使用二分查找,但是这里需要考虑的问题就是插入位置在哪里。这里我们考虑区间是左闭右闭的情况。

class Solution:def searchInsert(self, nums: List[int], target: int) -> int:left = 0right = len(nums) - 1while left <= right:mid = (left + right) // 2if(nums[mid] == target):return midif(nums[mid]>target):right = mid - 1if(nums[mid] < target):left = mid + 1return right + 1 

其余和二分查找没有区别,这里唯一需要注意的地方就是若未找到的话,返回索引可以有两种,left和right+1.这里的话可以自己找个例子写一下就可以了。
下面看这道题:

leetcode 34

在这里插入图片描述
你的理解基本上是正确的,尤其是关于使用两次二分查找来分别确定目标值的左边界和右边界的方法。下面我会进一步详细解释这个过程,确认你的理解,并补充一些可能的细节。

寻找右边界

当使用二分查找寻找右边界时,关键在于确保不错过最右侧的目标值。这可以通过以下步骤实现:

  1. 初始化left = 0, right = len(nums) - 1

  2. 循环条件while left <= right

  3. 中间索引mid = (left + right) // 2

  4. 比较逻辑

    • 如果 nums[mid] == target,则更新 left = mid + 1。这是因为我们需要确认是否有更靠右的相同目标值,所以我们将搜索范围向右推进。
    • 如果 nums[mid] > target,则更新 right = mid - 1
    • 如果 nums[mid] < target,则更新 left = mid + 1
  5. 循环结束后:由于 left 最终指向目标值最后一次出现位置的下一个位置,所以正确的右边界是 left - 1

寻找左边界

寻找左边界的方法与寻找右边界类似,但方向相反:

  1. 初始化left = 0, right = len(nums) - 1

  2. 循环条件while left <= right

  3. 中间索引mid = (left + right) // 2

  4. 比较逻辑

    • 如果 nums[mid] == target,则更新 right = mid - 1。这是因为我们需要确认是否有更靠左的相同目标值,所以我们将搜索范围向左推进。
    • 如果 nums[mid] > target,则更新 right = mid - 1
    • 如果 nums[mid] < target,则更新 left = mid + 1
  5. 循环结束后:由于 right 最终指向目标值第一次出现位置的前一个位置,所以正确的左边界是 right + 1

结果验证

  • 目标值存在:左边界应该指向目标值的第一个位置,右边界应该指向目标值的最后一个位置。
  • 目标值不存在:如果目标值不存在,左边界和右边界的差应该正好为1,因为 right 停在小于目标值的最大位置,而 left 停在大于目标值的最小位置。

你的理解是正确的,而且你已经很好地掌握了二分查找在这种情况下的应用。这种方法确保了高效地找到目标值的确切位置或者确定其不存在。
具体程序如下:

class Solution:def searchRange(self, nums: List[int], target: int) -> List[int]:leftBoder = self.getleftboard(nums, target)rightBoder = self.getrightboard(nums, target)# 情况一if leftBoder == -2 or rightBoder == -2: return [-1, -1]# 情况三if rightBoder -leftBoder >1: return [leftBoder + 1, rightBoder - 1]# 情况二return [-1, -1]def getrightboard(self,nums,target):left = 0right = len(nums) - 1rightboard = -2while left <= right:mid = left + (right - left) // 2if nums[mid] > target:right = mid - 1else:left = mid + 1rightboard = leftreturn rightboarddef getleftboard(self,nums,target):left = 0right = len(nums) - 1leftboard = -2while left <= right:mid = left + (right - left) // 2if nums[mid] >= target:right = mid - 1leftboard = rightelse:left = mid + 1return leftboard

leetcode 69

在这里插入图片描述
在二分查找中,寻找左边界、右边界和寻找特定条件的最大或最小值虽然共享同样的基本结构,但确实存在一些关键的差异。我们可以通过比较这些方法的细节来理解这些差异。

当我们寻找左边界时,目标是找到数组中第一个等于目标值的元素的位置。对于这种情况,我们通常会在找到目标值时继续向左搜索(缩小右边界),以确保没有更早出现的相同值。
寻找右边界的目的是找到数组中最后一个等于目标值的元素的位置。在这种情况下,即使找到了目标值,我们也会继续向右搜索(增加左边界),以确保没有更晚出现的相同值。
在寻找特定条件下的最大或最小值时,如求整数 ( x ) 的平方根,我们的目标是找到最大的整数 ( k ),使得 ( k^2 \leq x )。这种情况下的二分查找与寻找右边界有点相似,因为我们在满足条件的情况下向右推进左边界,以尽可能增大 ( k ) 的值。当 ( k^2 ) 大于 ( x ) 时,我们需要减小 ( k )(缩小右边界)。
所以程序按照寻找右边界的写即可,返回left-1即可。

class Solution:def mySqrt(self, x: int) -> int:left = 1right = xif x == 0:return 0if x == 1:return 1while left <= right:mid = left +(right - left)//2if mid*mid > x:right = mid - 1else:left = mid + 1return left - 1

下面继续看一道类似的题目:

leetcode367

在这里插入图片描述
这道题其实我们完全可以接着上面69题的思路去做,稍加修改,因为上道题寻找的是右边界也就是刚好是第一个平方和大于num的数,所以我们再去计算下left-1的平方和是否等于num,如果等于就是有效的完全平方数,反之则不是。
具体程序如下:

class Solution:def isPerfectSquare(self, num: int) -> bool:left = 1right = numif num == 1:return Truewhile left <= right:mid = left +(right - left)//2if mid*mid > num:right = mid - 1else:left = mid + 1if right * right == num:return Trueelse:return False

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

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

相关文章

36岁,大龄剩男,聊聊2024的上半年......

不知道我在等什么,也不知道这样等了多久,相信看到这句话的你,可能也是一头雾水吧! 还是以往的风格写到哪算哪,写东西真的是看感觉和心情都具备,写出来的东西才更有灵性,或者说更容易引起共鸣吧! 我在逃避? 可以这么说,但也不完全是,在一部分事情开始收尾的时候,情绪…

Modbus转Ethernet/IP网关模块与汇川PLC通讯案例

Modbus转Ethernet/IP网关模块(XD-MDEP100)是一种用于将Modbus协议转换为Ethernet/IP协议的设备。在汇川PLC通讯中,使用Modbus转Ethernet/IP网关模块可以方便地实现与其他设备的数据传输和通信。Modbus转Ethernet/IP网关模块(XD-MDEP100)是一种用于将Modbus协议转换为Ether…

test_web4

web4 题目分析 和上一题显示的页面一样,用同样的方法尝试注入:出现报错:看来这题相比上一题增加了过滤。使用 shell_exec 同理:换个思路,尝试使用一句话木马连接服务器后台。根据发回的响应包可以确定这题使用的是 nginx 服务器:看看访问日志先,?url=/var/log/nginx/ac…

test_web4_2

根据发回的响应包可以确定这题使用的是 nginx 服务器:看看访问日志先,?url=/var/log/nginx/access.log:尝试使用日志包含写入一句话木马,往 User-Agent 字段传入一句话木马 <?php @eval($_POST[web4]);?>传入后的日志增加一条记录:使用中国蚁剑连接日志文件,在 …

test_web4_1

web4 题目分析 和上一题显示的页面一样,用同样的方法尝试注入:出现报错:看来这题相比上一题增加了过滤。使用 shell_exec 同理:换个思路,尝试使用一句话木马连接服务器后台。

插片式远程 IO模块:Profinet总线耦合器博途配置

XD9000是Profinet总线耦合器,单个耦合器最多可扩展32个I/O模块!它们可以将输入/输出信号传送到远离控制中心的设备。Profinet总线耦合器是一种常用的设备,帮助连接IO模块和总线。XD9000是Profinet总线耦合器,单个耦合器最多可扩展32个I/O模块!它们可以将输入/输出信号传送…

frps内网穿透搭建http域名连接

起因是最近抽到了一台小鸡 1H512M2G,当然,安装完系统后就仅剩512M的存储空间了所以就打算搭建一个比较轻量的 我这里正好也没有公网ipv4,就搭建了frps(注意s -> server;c -> client下同) `frps配置 `frpc配置 serverAddr = "ip地址" serverPort = 10001 […

test1_1_1

web签到题 题目 web签到题分析 F12 打开 html 文件:将注释进行 Base64 解码得到 flag。 web2 题目 最简单的SQL注入分析 看着应该是 SQL 注入题。先尝试使用 admin 和 123456 登录,发现没有任何回显。看来报错被屏蔽了。显然 admin 栏如果注入成功则属于字符型注入。尝试使用…

河南萌新联赛2024第(一)场

个人感觉质量很不错的一套题,难度适中很适合我这种小白去做。不过由于在下能力有限,本文只会讲我通过的那些题。在难度上AHIK--FG--CB,接下来我会按这个难度顺序讲解。 A 造数我们模拟一下它从n到0的过程,要让n变小,肯定是在n>2的时候不断向下除以2,我们假设一个数4到9…

图中的环

图中的环2024.7.17 AcWing 4216. 图中的环:https://www.acwing.com/file_system/file/content/whole/index/content/4187139/一、题目二、题解 1. 基环树 如下图所示,基环树中只有一个环,且整个图是联通的。可以推断出它的性质:连通图;节点数=边数。2. 并查集 两个基本操作…

01-数值类型

01. 数值类型Python基本数据类型注意:英文后面跟上括号,我们统称为函数 eg: float()、int()严格意义上来说,布尔值并不归类到数值类型,但写项目的过程中,可能会用 0 和 1 进行判断,0 和 1 相当于布尔值的 False 和 True,所以暂时把布尔值归为数值类型拓展:在python中,…

李沐动手学深度学习V2-chapter_linear-networks

李沐动手学深度学习V2 文章内容说明 本文主要是自己学习过程中的随手笔记,需要自取 课程参考B站:https://space.bilibili.com/1567748478?spm_id_from=333.788.0.0 课件等信息原视频简介中有线性回归从零实现 导入包 %matplotlib inline import random import torch from d2…