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

文章详细介绍了如何使用二分法在Python中实现查准功能,分别处理了数组为空、只有一个元素和包含多个元素的情况。在查找过程中,通过不断调整中间值的计算方式避免超出范围,并确定目标元素的第一个和最后一个下标。
摘要由CSDN通过智能技术生成

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
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值