用python实现二分法在排序数组(列表)中查找元素的第一个和最后一个位置

1.概述

       实现二分法的查准分三种情况,第一种是一种是nums = [];即l列表为空,一种是nums列表只有一个元素,nums元素个数大于1为最后一种。没找到输入[-1,-1],找到输出对应下标。nums(数组) 和target(要搜索的元素)


2.nums为空-数组为空

 not nums 如果nums 为返回值为False,not使其反转为True

if not nums:
    print([-1, -1])

3.len(nums)等于1

  len(nums) = 1,即数组只有一个元素,若等于即第一个和最后一个都是它。没有则输出[-1,-1]。

也可以用  target in nums 判断(不推荐,毕竟学算法,尽量不用内置函数和python独有的判断符)

if nums[0] == target:
      print([0, 0])
else:
      print([-1, -1])

4.len(nums) 大于 1的情况

求中间值为什么不要 m1 = (l1 + r1)//2,而是下面的式子

m1 = l1 + (r1 - l1) // 2

因为r1,l1无限接近于规定的最大数,一旦相加就超过了规定的范围限制。取l1和r1的一半不会超出范围。

分别求出要找的第一个元素和最后一个元素的下标。

因为要求第一个元素,当发现nums[m1] == target时,要看它左边还有没有和它一样的数,所以m1要变小, 即右边的区间取m1,如果目标值大于取到的数组值,说明m1小了,要取右边的,l1 = m1 + 1,取l1 = m1,注意 // 2 不加一,3//2=0, 2//2=0肯会还是等于上一个m1值,会陷入死循环。而目标值小于取到的数组值不用担心,因为r1 变化大。再者出现就直接得结果了(可以自己用笔算一下)

 l1 = 0
    r1 = len(nums) - 1
    while l1 < r1:
        m1 = l1 + (r1 - l1) // 2
        if nums[m1] == target:
            r1 = m1
        elif nums[m1] > target:
            r1 = m1
        elif nums[m1] < target:
            l1 = m1 + 1
    if nums[l1] == target:
        R1 = l1

求最后一个元素,比求第一个元素要注意的是如果nums[m2] == target,你要注意取右边的数,所有m2值变大,l2 =  m2 + 1 ,这里也要注意 // 2 不加一的话,3//2=0, 2//2=0,会陷入死循环。我写的代码,发现后面没有相等的值了,就直接停止循环,输出 r2 = m2.

 l2 = 0
    r2 = len(nums) - 1
    while l2 < r2:
        m2 = l2 + (r2 - l2) // 2
        if nums[m2] == target:
            if nums[m2 + 1] == target:
                l2 = m2 + 1
            else:
                r2 = m2
                break
        elif nums[m2] < target:
            l2 = m2 + 1
        elif nums[m2] > target:
            r2 = m2
    R2 = r2

最终实现代码

nums = list(map(int,input().split(' '))) //加的输入,可不用。
target = int(input())
R1 = -1
R2 = -1
if not nums:
    print([-1, -1])
elif len(nums) == 1:
    if nums[0] == target:
        print([0, 0])
    else:
        print([-1, -1])
else:
    l1 = 0
    r1 = len(nums) - 1
    while l1 < r1:
        m1 = l1 + (r1 - l1) // 2
        if nums[m1] == target:
            r1 = m1
        elif nums[m1] > target:
            r1 = m1
        elif nums[m1] < target:
            l1 = m1 + 1
    if nums[l1] == target:
        R1 = l1
    l2 = 0
    r2 = len(nums) - 1
    while l2 < r2:
        m2 = l2 + (r2 - l2) // 2
        if nums[m2] == target:
            if nums[m2 + 1] == target:
                l2 = m2 + 1
            else:
                r2 = m2
                break
        elif nums[m2] < target:
            l2 = m2 + 1
        elif nums[m2] > target:
            r2 = m2
    R2 = r2
    if R1 == -1:
        print([-1, -1])
    else:
        print([R1, R2])

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,我可以为您提供一个递归的二分查找算法来解决这个问题。 假设我们要在已排序数组 `arr` 查找元素 `target` 出现的第一个位置,我们可以编写以下递归函数: ```python def binary_search(arr, target, left, right): if left > right: return -1 mid = (left + right) // 2 if arr[mid] == target: if mid == 0 or arr[mid-1] < target: return mid else: return binary_search(arr, target, left, mid-1) elif arr[mid] > target: return binary_search(arr, target, left, mid-1) else: return binary_search(arr, target, mid+1, right) ``` 该函数接受四个参数:已排序数组 `arr`、要查找元素 `target`、当前查找区间的左右边界 `left` 和 `right`。函数首先判断查找区间是否有元素,如果没有则返回 `-1` 表示查找失败。然后计算出位置 `mid`,如果 `arr[mid] == target`,则表示找到了目标元素,接下来判断它是否是第一个出现的位置,如果是则返回 `mid`,否则继续在左半边查找。如果 `arr[mid] > target`,则说明目标元素在左半边,继续在左半边查找;如果 `arr[mid] < target`,则说明目标元素在右半边,继续在右半边查找最后,我们可以调用该函数来查找元素第一次出现的位置: ```python arr = [1, 2, 3, 3, 3, 4, 5, 6] target = 3 left = 0 right = len(arr) - 1 print(binary_search(arr, target, left, right)) # 输出 2 ``` 在这个示例元素 `3` 第一次出现的位置是索引 `2`。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值