首页 > 编程语言 >二分搜索算法

二分搜索算法

时间:2022-11-16 21:36:03浏览次数:40  
标签:二分 nums mid 搜索算法 查找 目标值 left

目录


介绍

二分查找适用于已经排序的序列,通过对搜索区间折半的方式查找目标元素。

基本的二分搜索

基本的二分查找适用于在已经排序的无重复元素的序列中,查找一个目标值。。

思路

查找左边界的二分搜索,假设查找区间为 \([0, n)\) ,那么:

  • 如果中间元素大于目标值,右指针移动到 \(mid - 1\) 位置;
  • 如果中间元素小于目标值,左指针移动到 \(mid + 1\) 的位置;
  • 如果中间元素等于目标值,则结束查找,返回结果;

注意:如果遍历完整个序列,都没有找到匹配的值,那说明序列中不包含目标值。

代码实现:

from typing import List
def binary_search(nums: List[int], target: int):
    left, right = 0, len(nums) - 1
    while left <= right:
        mid = left + (right - left) // 2
        if nums[mid] == target:
            return mid
        elif nums[mid] < target:
            left = mid + 1
        else:
            right = mid - 1
    return -1

if __name__ == "__main__":
    print(binary_search([1, 2, 3, 4, 5, 6, 7, 8], 6))

查找左边界的二分搜索

如果已经排序的序列包含重复元素,即待查找的目标值target可能包含重复元素,就需要换一种方式查找。
例如,我们要从升序的序列\(nums = [1, 2, 3, 4, 5, 5, 5, 6, 6, 7, 8]\),中查找第一个出现的元素\(5\)的序号,那么就要用到查找左边界的二分搜索方法。

思路

查找左边界的二分搜索,假设查找区间为 \([0, n)\) ,那么:

  • 如果中间元素大于等于目标值,右指针移动到 \(mid\) 位置;
  • 如果中间元素小于目标值,左指针移动到 \(mid + 1\) 的位置;

如果查找完所有的元素后,左指针针超出数组边界,或者,左指针指向的元素不等于目标值,则,原始数组中不存在目标值;否则,就返回左指针

代码实现:

from typing import List

def binary_search_left(nums: List[int], target):
    left, right = 0, len(nums)
    while left < right:
        mid = left + (right - right) // 2
        if nums[mid] >= target:
            right = mid
        else:
            left = mid + 1

    if left >= len(nums) or nums[left] != target:
        return -1

    return left

if __name__ == "__main__":
    print(binary_search_left([1, 2, 3, 4, 5, 5, 5, 7, 7, 7, 8], 5))
    print(binary_search_left([1, 2, 3, 4, 5, 5, 5, 7, 7, 7, 8], 6))

查找右边界的二分搜索

同理,如果我们要从升序序列中查找出最后一次出现的元素,就要通过查找右边界的二分搜索方法。

思路

查找右边界的二分搜索,假设查找区间为 \([0, n)\) ,那么:

  • 如果中间元素大于目标值,右指针移动到 \(mid\) 位置;
  • 如果中间元素小于等于目标值,左指针移动到 \(mid + 1\) 的位置;

如果指针 \(left - 1\) 不在数组内,或者,指针 \(left - 1\) 指向的元素不等于目标值,那么原始数组不包含目标值,否则,就返回指针 \(left - 1\)。

代码实现:

from typing import List

def binary_search_right(nums: List[int], target):
    left, right = 0, len(nums)
    while left < right:
        mid = left + (right - left) // 2
        if nums[mid] <= target:
            left = mid + 1
        else:
            right = mid

    if left -1 <= 0 or nums[left - 1] != target:
        return -1
    return left - 1

if __name__ == "__main__":
    print(binary_search_right([1, 2, 3, 4, 5, 5, 5, 6, 6, 7, 8], 5))
    print(binary_search_right([1, 2, 4, 5, 5, 5, 6, 6, 7, 8], 3))

标签:二分,nums,mid,搜索算法,查找,目标值,left
From: https://www.cnblogs.com/larry1024/p/16897559.html

相关文章

  • 代码随想录算法训练营Day01|704. 二分查找、27. 移除元素
    代码随想录算法训练营Day01|704.二分查找、27.移除元素704.二分查找题目链接:704.二分查找首先注意题干的描述:题干描述说明了元素是升序排列的,否则需要调用sort进行......
  • 代码随想录算法训练营第一天| 704. 二分查找、27. 移除元素
    目录两道题704.二分查找27.移除元素省流两道题704.二分查找  1、数组算是最简单,也最不抽象的数据结构了。二分法,我也在学习路上听过不少次,所以是实际实现也很快,没有......
  • 代码随想录算法训练营第一天| 704. 二分查找、27. 移除元素。
    今日任务数组理论基础,704.二分查找,27.移除元素1数组理论基础文章链接:https://programmercarl.com/%E6%95%B0%E7%BB%84%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html......
  • 力扣 153. 寻找旋转排序数组中的最小值 [二分变种]
    153.寻找旋转排序数组中的最小值已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums=[0,1,2,4,5,6,7] 在变......
  • 20221115_T3A+_贪心二分
    题意你在和Yazid做游戏。Yazid给了你一棵\(n\)个节点的树,并让你删除这棵树上的恰好\(k\)条边,使得整棵树被分成\(k+1\)个连通块。你觉得太简单了,随便删k条边......
  • PHP二分法
    classHalfFind{/***@desc二分法查找效率老高了前提:必须是有序的数组*@desc二分法时间复杂度为O(logn)**@param$nums*......
  • PTA 数据结构 二分查找
    本题要求实现二分查找算法。函数接口定义: PositionBinarySearch(ListL,ElementTypeX); 其中List结构定义如下: typedefintPosition;typedefstructLNo......
  • 二分模板
    二分是基础算法之一,常用于答案有单调性的题目,或者穷举会超时的题目intsearch(intl,intr){while(l+1<r){intmid=l+(r-l)>>1;//防溢......
  • WQS二分
    用于求解具有单调性的从一堆物品中恰好选need个且满足权值最大/小化等要求的问题。无向带权连通图,每条边是黑色或白色。求一棵最小权的恰好有need条白色边的生成树。二分......
  • 整体二分
    整体二分是将所有操作离线下来,对多组询问同时进行二分。将所有操作按照时间顺序存入数组,设[st,ed]为答案的定义域,即询问的区间,[l,r]为答案的值域。二分答案的值域,对于每......