二分搜索的模板(一)

二分搜索是算法搜索一部分的重要内容。虽然变化多端,但仍有迹可循,有法可依。记录一下在网上遇到的模板~

这个模版的核心是将二分搜索(binary search)问题转化成:在给定升序数组(没有相同元素)中,寻找大于等于 target 值的最小索引或小于等于 target 值的最大索引。有几点需要注意:

  1. 初始化:start = -1,end = array.length
  2. 循环判断条件:start + 1 < end。 表示当指针指到两个元素相邻或者相交的时候, 循环停止。
  3. 求中间值:mid = start + (end - start) / 2,防止溢出。(Python不用考虑,但Python的除号是 //)
  4. 使用迭代而不是递归进行二分查找,因为工程中递归写法存在溢出的可能。
  5. while终止条件应为 start + 1 < end 而不是 start <= end,start == end 时可能出现死循环。循环终止条件是相邻或相交元素时退出。但是初始化时start < end,所以一定是start + 1 == end时退出循环。
  6. 该模板把数组 -1 和 len(array) 的位置考虑在内:如果大于等于 target 值的最小索引不存在,则返回 len(array);如果小于等于 target 值的最大索引不存在,则返回 -1。

该模板的Python代码如下:

class Solution:
    def searchInsert1(self, array, target):
        # 寻找大于等于 target 值的最小索引
        if not array:
            return 0
        
        start = -1
        end = len(array)
        while start + 1 < end:
            mid = start + (end - start) // 2
            if array[mid] < target:
                start = mid
            else:
                end = mid
        
        return end
    
    def serachInsert2(self, array, target):
        # 寻找小于等于 target 值的最大索引
        if not array:
            return 0
        
        start = -1
        end = len(array)
        while start + 1 < end:
            mid = start + (end - start) // 2
            if array[mid] > target:
                end = mid
            else:
                start = mid
        
        return start

题目:lintcode 60. Search Insert Position & leetcode 35. Search Insert Position

题目描述:给定一个排序数组A和一个目标值target,如果在数组中找到目标值则返回索引。如果没有,返回到它将会被按顺序插入的位置。你可以假设在数组中无重复元素。

根据上面模板进行解题,即寻找大于等于 target 值的最小索引。Python代码如下:

class Solution:
    def searchInsert(self, A, target):
        if not A:
            return 0
        
        start, end = -1, len(A)
        while start + 1 < end:
            mid = start + (end - start) // 2
            if A[mid] < target:
                start = mid
            else:
                end = mid
        return end

参考资料:

  1. lintcode No.60 Search Insert Position
  2. Binary Search - 二分搜索
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值