Python中二分法查找某个元素的索引(1)

对于给定的整数集合,要想查找某个元素是否存在我们可以使用 index 操作,如下:

nums = [0, 1, 1, 2, 3, 3, 3, 4, 4, 5, 6, 7, 7, 8, 8, 9, 9, 9, 9]
print(nums.index(5)) # 输出索引 9
print(nums.index(10)) # 报错

这里我们使用二分法进行查找,直接上代码:

nums = [0, 1, 1, 2, 3, 3, 3, 4, 4, 6, 7, 7, 8, 8, 9, 9, 9, 9]
#       0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17

def Bisection(num, n):
    left = 0
    right = len(num)-1

    while left <= right:
        mid = (left+right) // 2

        if nums[mid] == n:
            return mid
        
        if nums[left] <= n < nums[mid]:
            right = mid -1
        else:
            left = mid + 1

    return -1
    
for i in range(-3, 13):
    print(i, Bisection(nums, i))

输出:

-3 -1  # 找不到返回 -1
-2 -1
-1 -1
 0  0  
 1  1  
 2  3  
 3  5  # 找到 返回其索引
 4  8
 5 -1
 6  9
 7  10
 8  13
 9  15
10 -1
11 -1
12 -1

上述我们基于的一个升序序列,假如对 nums 某个位置进行首位置换一下,比如 nums 变成下面的样子。

nums = [4, 6, 7, 7, 8, 8, 9, 9, 9, 9, 0, 1, 1, 2, 3, 3, 3, 4]

此时,需要修改一下判别条件,左一半或者右一半一定有一个升序序列。

nums = [4, 6, 7, 7, 8, 8, 9, 9, 9, 9, 0, 1, 1, 2, 3, 3, 3, 4]
#       0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17

def Bisection(num, n):
    left = 0
    right = len(num) - 1

    while left <= right:
        mid = (left+right) // 2

        if num[mid] == n:
            return mid

        if num[left] <= num[mid]:          # 判断左一半是不是升序的

            if num[left] <= n < num[mid]:  # 如果是升序的话 判断目标是否在 left mid 里面
                right = mid - 1            # 在里面的话更新 right
            else:                          # 虽然是升序 但目标不在这里面
                left = mid + 1             # 更新 left 直接舍去这部分

        else:                              # 右一半是升序的

            if num[mid] < n <= num[right]: # 判断目标是否在 mid right 里面
                left = mid + 1             # 在里面更新 left
            else:                          # 目标不在这里面 更新 right
                right = mid - 1
                
    return -1

for i in range(-3, 13):
    print(i, Bisection(nums, i))

输出:

-3 -1
-2 -1
-1 -1
 0  10
 1  11
 2  13
 3  15
 4  0
 5 -1
 6  1
 7  3
 8  5
 9  8
10 -1
11 -1
12 -1

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值