二分问题的基本思想及其实现(python3)

核心思想:

减而治之(逐渐缩小问题规模)。我们总是在区间[left..right]里查找元素目标。

(注意是左闭右闭区间。为什么不是「左闭右开」呢?「左闭右开」当然可以,但是我们 不想把精力花在「右边界是不是可以取到」这件事情上,并且 任意一个「左闭右开」区间一定唯一对应一个「左闭右闭」区间,所以到底是开区间还是闭区间,保持一致就可以。根据 mid 位置是不是目标元素,进而判断 mid 的左边是。)

 

基本思路:

根据待搜索区间里的中间元素 nums[mid] 与 target 的值的大小关系,判断下一轮搜索需要在哪个区间里查找,进而设置 left 和 right 的值。分为如下三种情况:

如果 nums[mid] == target,运气很好,找到了目标元素,返回 mid ;

如果 nums[mid] > target,说明 mid 以及 mid 的 右边 的所有元素一定都比 target 大,下一轮搜索需要在区间 [left..mid - 1] 里查找,此时设置 right = mid - 1;

如果 nums[mid] < target,说明 mid 以及 mid 的 左边 的所有元素一定都比 target 小,下一轮搜索需要在区间 [mid + 1..right] 里查找,此时设置 left = mid + 1。

 

把待搜索区间分成两个部分:

这个地方我起初没有理解,后来我悟了。这部分才是关键啊。

我们考虑区间的完整性,所以mid肯定只能在左右两个区间中的一个:

情况1:mid被分到左区间,区间变成[left,mid] 和 [mid+1,right]

情况2:mid被分到右区间,区间变成[left,mid-1] 和 [mid,right]

 

循环结束条件:

退出循环的时候,说明区间里不存在目标元素,返回 -1。那么循环结束的条件的是什么?

while (left < right)

在上面把待搜索区间分成两个部分的划分下,退出循环以后一定会有 left == right 成立,因此我们在退出循环以后,就不需要考虑到底返回 left 还是返回 right。

介绍一个比较好的经验:

我们在写判断条件时,通常把容易想到的,不容易出错的逻辑写在 if 的里面,这样就把复杂的、容易出错的情况放在了 else 的部分。

 

实现:

我们结合上面的思想来做一道题:

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

你可以假设数组中无重复元素。

本题目要求我们找到第一个大于等于target的元素的位置,那么不容易出错的就是:小于target的元素就不是我们想要寻找的答案。所以我们可以这样写if语句:

if(nums[mid]<target):
    //下一轮搜索区间就是[mid+1, right]
    left = mid + 1

剩余的情况放在else中:

else:
    //下一轮搜索区间是[left, mid]
    right = mid

所以这道题的答案很显然了

class Solution:
    def searchInsert(self, nums: List[int], target: int) -> int:
    	n = len(nums)
    	l,r = 0, n-1

    	# 特殊判断 
    	if nums[n-1] < target:
    		return n

    	# 确保target<=nums[len-1]
    	while(l<r):
    		m = l + (r - l)//2
    		if nums[m] < target:
    			l = m + 1
    		else:
    			r = m
    	return l

参考文章:

https://leetcode-cn.com/problems/search-insert-position/solution/te-bie-hao-yong-de-er-fen-cha-fa-fa-mo-ban-python-/

 

全部评论

相关推荐

背景&nbsp;双一流本硕&nbsp;双非大圆满&nbsp;只找游戏开发相关的岗位。&nbsp;8&nbsp;月初开始秋招到现在&nbsp;投了四五十家吧,&nbsp;目前两&nbsp;offer,&nbsp;不打算继续投了,把剩下的流程走完就开始沉淀了。目前两&nbsp;offer&nbsp;一个是网易互娱测开&nbsp;base&nbsp;广州,一个是江娱互动客户端开发&nbsp;base&nbsp;北京。应该确定网易这个了,说实话北京这个我挺想去的,这家的产品和工作氛围我了解了也不错,是那种踏实做事的,可惜我是广东人。网易的测开是调剂的二志愿,看了下有内部转岗机会,所以打算后面找个时间提前实习,沉淀下再做一个&nbsp;demo&nbsp;作品,写一些&nbsp;shader,增强下图形学渲染的能力,再学点编辑器开发。看到时候内部转岗或者春招继续投客户端开发这样。后面还能再动摇的话应该就灵犀或者腾子了吧(假如这两家确认的是客户端开发岗的话)。-----------------------补下timeline网易互娱&nbsp;测开&nbsp;8.2笔试&nbsp;&nbsp;8.21&nbsp;技术面&nbsp;&nbsp;8.29&nbsp;leader&amp;HRBP面(终面)&nbsp;9.8&nbsp;录用审核(之前一直显示面试中)9.14&nbsp;oc江娱互动&nbsp;客户端开发&nbsp;8.29主程面&nbsp;9.3&nbsp;制作人面&nbsp;9.5&nbsp;BOSS面&nbsp;9.11&nbsp;口头OC&nbsp;9.15&nbsp;正式offer后面考虑了一下&nbsp;&nbsp;感觉还是能走开发就开发吧,测开不太感兴趣,要内部活水转岗还要满1年才能申请。。
点赞 评论 收藏
分享
从大一开始就开始学习Java,一路走来真的不算容易,每次面试都被压力,不过这次终于达成了自己的一大心愿!时间线和面经:8.17-投递9.1-一面实习+项目拷打看门狗机制讲一下redis加锁解锁的本身操作是什么Lua脚本是干什么的udp和tcp讲一下流量控制讲一下令牌桶算法说一下大端和小端是什么线程和协程有什么区别怎么切换协程切换的时候具体做了什么对于程序来说,你刚才提到的保存和恢复现场,这个现场有哪些信息udp优势现在有一个客户端和服务端,要实现TCP的通信,我们的代码要怎么写服务器怎么感知有新的连接怎么处理多个客户端的请求连接TCP怎么处理粘包和分包现在有两个文件,然后每个文件都有一亿条URL,每个的长度都很长,要怎么快速查找这两个文件共有的URLHashmap底层说一下怎么尽量提升插入和查询的效率如果要查找快,查询快,还有解决非空的问题,怎么做LoadingCache了解吗手撕:堆排序9.4-二面部门的leader,超级压力面拷打实习+项目,被喷完全没东西类的加载到垃圾回收整个底层原理讲一遍类加载谁来执行类加载器是什么东西,和进程的关系Java虚拟机是什么东西,和进程的关系如果我们要执行hello&nbsp;world,那虚拟机干了什么呢谁把字节码翻译成机器码,操作时机是什么Java虚拟机是一个执行单元吗Java虚拟机和操作系统的关系到底什么,假如我是个完全不懂技术的人,举例说明让我明白一个操作系统有两个Java程序的话,有几个虚拟机有没有单独的JVM进程存在启动一个hello&nbsp;world编译的时候,有几个进程JVM什么时候启动比如执行一条Java命令的时候对应一个进程,然后这个JVM虚拟机到底是不是在这个进程里面,还是说要先启动一个JVM虚拟机的进程垃圾回收机制的时机能手动触发垃圾回收吗垃圾回收会抢占业务代码的CPU吗垃圾回收算法简单说说垃圾回收机制的stop&nbsp;the&nbsp;world存在于哪些时机垃圾回收中的计算Region的时候怎么和业务代码并行执行假如只有一个线程,怎么实现并行Java为什么要这么实现Java效率比C++慢很多,那为什么还要这样实现Java虚拟机到底是什么形式存在的说一下Java和C++的区别还有你对Java设计理念的理解无手撕面试结束的时候,我真的汗流浃背了,面试官还和我道歉,说他是故意压力面想看看我的反应的,还对我给予了高度评价:我当面试官这么多年,你是我见过最好的一个9.9-三面临时通知的加面,就问了三十分钟项目9.11-hr面问过往经历,未来计划,想从腾讯实习中得到什么?当场告知leader十分满意我,所以直接ochr面完一分钟官网流程变成录用评估中,30分钟后mt加微信告知offer正在审批9.15-offer这一次腾讯面试体验真的不错,每个面试官能感觉到专业能力很强,反馈很足,比起隔壁某节真是好太多以后就是鹅孝子了
三本咋了:当面试官这么多年你是我见过的最好的一个
你面试被问到过哪些不会的...
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务