在等分搜索中找到最左边的重复项

时间:2019-04-11 10:03:06

标签: python

我阅读了Binary search algorithm - Wikipedia,一分为二地搜索了重复项的最左侧元素
伪代码:

function binary_search_leftmost(A, n, T):
    L := 0
    R := n
    while L < R:
        m := floor((L + R) / 2)
        if A[m] < T:
            L := m + 1
        else:
            R := m
    return L

在python中实现

def search_leftmost(nums: List[int], target: int) -> List[int]:
    if len(nums) < 1: return [-1, -1]
    lo = 0
    hi = len(nums)
    logging.debug(f"nums:{list(enumerate(nums))}, target: {target}")
    while lo < hi: 
        mid = (lo+hi) // 2
        logging.debug(f"lo:{lo} mid:{mid} hi:{hi}")
        if target > nums[lo]:
            lo = mid + 1
        else:
            hi = mid 
    logging.debug(f"lo: {lo}")
    return lo

不幸的是,当使用nums = [5,7,7,8,8,8,8,10]; target = 8

进行测试时
$ python 0.bi_search.py 
DEBUG nums:[(0, 5), (1, 7), (2, 7), (3, 8), (4, 8), (5, 8), (6, 8), (7, 10)], target: 8
DEBUG lo:0 mid:4 hi:8
DEBUG lo:5 mid:6 hi:8
DEBUG lo:5 mid:5 hi:6
DEBUG lo: 5

返回5,它既不是最左也不是最右。

我的实现有什么问题?

1 个答案:

答案 0 :(得分:1)

问题出在执行中。

伪代码

if A[m] < T:
  L := m + 1

实现为

if target > nums[lo]: # this should be if nums[mid] < target:
    lo = mid + 1

我已对其进行更新,并且它按预期运行:

def search_leftmost(nums, target):
    lo = 0
    hi = len(nums)
    while lo < hi: 
        mid = (lo+hi) // 2
        if nums[mid] < target:
            lo = mid + 1
        else:
            hi = mid
    return lo

if __name__ == "__main__":
    nums = [5,7,7,8,8,8,8,10]
    target = 8    
    assert search_leftmost(nums, target)== 3


    nums = [5,7,7,8,8,8,8,10]
    target = 7
    assert search_leftmost(nums, target) == 1


    nums = [5,7,7,8,8,8,8,10]
    target = 10
    assert search_leftmost(nums, target) == 7

    print("Done")

根据Wiki

  

即使T不在数组中,L   是T在数组中的排名,还是   数组中小于T的元素。