栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

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

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

给定升序的整数列表:

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

但是,上面的 nums 里有的元素出现不止一次,我们需要找出目标第一次出现的索引或者最后一次出现的索引,(参考上一篇)有:

第一次出现的索引:

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_left(num, n):
    left = 0
    right = len(num)-1
 
    while left <= right:
        mid = (left+right) // 2
        
        if n <= nums[mid]:
            right = mid -1
        else:
            left = mid + 1
 
    return left
    
for i in list(set(nums)):
    print(i, Bisection_left(nums, i))
0 0
1 1
2 3
3 4
4 7
6 9
7 10
8 12
9 14
# 对于不在 nums 的元素可以用下面的命令判断
for i in [-1, 5, 10]:
    index = Bisection_left(nums, i)
    
    if nums[index] != i or index > len(nums):
        print(i, -1)
# -1 -1
# 5  -1
# 10 -1

最后一次出现的索引:

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_right(num, n):
    left = 0
    right = len(num)-1
 
    while left <= right:
        mid = (left+right) // 2
        
        if n >= nums[mid]:
            left = mid + 1  
        else:
            right = mid -1
            
    return right
    
for i in list(set(nums)):
    print(i, Bisection_right(nums, i))
0 0
1 2
2 3
3 6
4 8
6 9
7 11
8 13
9 17
# 对于不在 nums 的元素可以用下面的命令判断
for i in [-1, 5, 10]:
    index = Bisection_right(nums, i)
    
    if nums[index] != i or index < 0:
        print(i, -1)
# -1 -1
# 5  -1
# 10 -1

在这里我们是否问道:能否统计目标在列表中出现的首次和末次的索引,当然可以。

第一种方法:即统计出目标第一次出现的索引 和 最后一次出现的索引

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_left(num, n):
    left = 0
    right = len(num)-1
 
    while left <= right:
        mid = (left+right) // 2
        
        if n <= nums[mid]:
            right = mid -1
        else:
            left = mid + 1
 
    return left
    
def Bisection_right(num, n):
    left = 0
    right = len(num)-1
 
    while left <= right:
        mid = (left+right) // 2
        
        if n >= nums[mid]:
            left = mid + 1  
        else:
            right = mid -1
            
    return right
    
for i in list(set(nums)):
    left = Bisection_left(nums, i)
    right = Bisection_right(nums, i)
    print(i, [left, right])
0 [0, 0]
1 [1, 2]
2 [3, 3]
3 [4, 6]
4 [7, 8]
6 [9, 9]
7 [10, 11]
8 [12, 13]
9 [14, 17]

第二种方法:即统计出目标第一次出现的索引 和 目标+1 第一次出现的索引

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_left(num, n):
    left = 0
    right = len(num)-1
 
    while left <= right:
        mid = (left+right) // 2
        
        if n <= nums[mid]:
            right = mid -1
        else:
            left = mid + 1
 
    return left

for i in list(set(nums)):
    start = Bisection_left(nums, i)
    end = Bisection_left(nums, i+1) - 1 # 这里不论 i+1 是否在nums里面,如果不在的话也就是下一个元素的第一个索引
    print(i, [start, end])              # 最后一个元素的 i+1 会超出边界 在这里就是 10 的索引是18
0 [0, 0]
1 [1, 2]
2 [3, 3]
3 [4, 6]
4 [7, 8]
6 [9, 9]
7 [10, 11]
8 [12, 13]
9 [14, 17]
def Bisection_right(num, n):
    left = 0
    right = len(num)-1
 
    while left <= right:
        mid = (left+right) // 2
        
        if n >= nums[mid]:
            left = mid + 1  
        else:
            right = mid -1
            
    return right
    
for i in list(set(nums)):
    left = Bisection_right(nums, i-1) + 1 # 这里不论 i-1 是否在nums里面,如果不在的话也就是上一个元素的最后一个索引
    right = Bisection_right(nums, i)      # 第一个元素的 i-1 会超出边界 在这里就是 -1 的索引是-1
    print(i, [left, right])
0 [0, 0]
1 [1, 2]
2 [3, 3]
3 [4, 6]
4 [7, 8]
6 [9, 9]
7 [10, 11]
8 [12, 13]
9 [14, 17]

第三种方法:在给出一个双指针的方法

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 Pointe(num, n):
    left = 0
    right = len(num)-1
 
    while left <= right:     
        if num[left] == n:
            left = left
        else:
            left += 1

        if num[right] == n:
            right = right
        else:
            right -= 1      

        if num[left] == num[right]:
            break

    return [left, right]

for i in list(set(nums)):
    print(i, Pointe(nums, i)) 
0 [0, 0]
1 [1, 2]  
2 [3, 3]  
3 [4, 6]  
4 [7, 8]  
6 [9, 9]  
7 [10, 11]
8 [12, 13]
9 [14, 17]

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/822455.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号