leetcode--二分查找

本文探讨了三个LeetCode题目,分别是704.二分查找、278.第一个错误的版本和35.搜索插入位置,它们都涉及到二分查找算法。在704题中,直接应用基本的二分查找;278题需要找到第一个错误的版本,通过调整边界条件来找到目标;35题则是在排序数组中找到目标值的插入位置,同样采用二分查找优化解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二分查找

题号:704.二分查找

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/binary-search

思路:这就是最基础的二分查找了,直接一直二等分,知道找到目标值就返回下标(如果目标值比中值小,就将右边界设置为中值,如此循环,反之亦然)

代码:

class Solution(object):
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """

        
        n = len(nums)
        first = 0
        last = n - 1
        while first <= last:
            mid = (first + last) // 2
            if target == nums[mid]:
                return mid
            elif target < nums[mid]:
                last = mid - 1
            else:
                first = mid + 1

        return -1

题号:278.第一个错误的版本

你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。

假设你有 n 个版本 [1, 2, …, n],你想找出导致之后所有版本出错的第一个错误的版本。

你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/first-bad-version

思路:首先这也是个二分查找问题,只不过有点变化,因为根据题目所说我们是要找到第一个出问题的版本,同时第一个出错版本的后面的版本都是错的,也就说明使用 isBadVersion(version) 函数时,在第一个错误版本后面的所有版本都会返回True,所以就会有一个核心的问题需要解决:
如何确定第一个版本?
1.如果第一个版本在mid的左边?
2.如果第一个版本在mid的右边?
3.如果第一个版本刚好就在mid?

解决方案:
首先分为两种情况
1.isBadVersion(mid)为True,这个版本是错的
2.isBadVersion(mid)为False,这个版本是对的

如果是:说明第一个版本一定在它的左侧或者就是它本身,如何验证呢,可以通过设置last(右侧边界)=mid,以此二分查找来不断地接近第一个版本,当first == last 的时候,就说明此时已经是第一个版本,返回该值

**如果不是:**说明第一个版本一定在它的右侧,可以通过设置:first(左侧边界)=mid +1,然后继续二分查找,直到找到一个错误版本,才能进入上面的循环

代码:

# The isBadVersion API is already defined for you.
# @param version, an integer
# @return a bool
# def isBadVersion(version):

class Solution(object):
    def firstBadVersion(self, n):
        """
        :type n: int
        :rtype: int
        """
        first = 1
        last = n
        while first <= last:
            mid = (first + last) // 2
            if isBadVersion(mid):
                last = mid  
                if first == last:
                    return mid
            else:
                first = mid + 1

或者

class Solution(object):
    def firstBadVersion(self, n):
        """
        :type n: int
        :rtype: int
        """
        first = 1
        last = n
        while first < last:
            mid = (first + last) // 2
            if isBadVersion(mid):
                last = mid  
                if first == last:
                    return mid
            else:
                first = mid + 1
        return first

上面两种代码的区别就是跳出 while 循环

题号: 35.搜索插入位置

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

请必须使用时间复杂度为 O(log n) 的算法。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/search-insert-position

思路:根据题目要求,可以把代码分为两部分,先查找数组中有没有目标值,如果有,就返回索引,没有就再比较目标值的大小,并返回顺序插入的位置(并不是插入之后再返回,只是逻辑上的处理而已
比较分为三种情况:
1.比mid值大
2.与mid值相等
3.比mid值小

解决:
通过二分查找没找到该目标值的话,此时的mid值其实就已经与目标值相邻了
1.如果比mid值大,那么返回mid+1
2.3. 其实<=mid 值是一种情况,那就是把该mid位置上原有的值给替代就可以了,也就是 返回mid

代码:

class Solution(object):
    def searchInsert(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        n = len(nums)
        first = 0 
        last = n-1
       
        while first <= last:
            mid = (first + last) // 2
            if target == nums[mid]:
                return mid
            elif target < nums[mid]:
                last = mid - 1
            else:
                first = mid + 1
        
        if target > nums[mid]:
            return mid + 1
        else:
            return mid
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值