Python 如何使用二进制搜索计算排序数组中的唯一数?

Python 如何使用二进制搜索计算排序数组中的唯一数?,python,python-3.x,algorithm,binary-search,Python,Python 3.x,Algorithm,Binary Search,我试图使用二进制搜索来计算排序数组中的唯一数。我需要从一个数字到下一个数字的变化的边缘来计数。我在考虑不使用递归来做这件事。有迭代方法吗 def unique(x): start = 0 end = len(x)-1 count =0 # This is the current number we are looking for item = x[start] while start <= end: middle = (st

我试图使用二进制搜索来计算排序数组中的唯一数。我需要从一个数字到下一个数字的变化的边缘来计数。我在考虑不使用递归来做这件事。有迭代方法吗

def unique(x):
    start = 0
    end = len(x)-1
    count =0
    # This is the current number we are looking for
    item = x[start]

    while start <= end:
        middle = (start + end)//2
        
        if item == x[middle]:
            start = middle+1
            
        elif item < x[middle]:
            end = middle -1
        
        #when item item greater, change to next number
        count+=1

    # if the number
    return count
    
unique([1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,5,5,5,5,5,5,5,5,5,5])
def唯一(x):
开始=0
结束=长度(x)-1
计数=0
#这是我们正在寻找的当前号码
项目=x[开始]

当启动工作代码时,利用二进制搜索(给定示例返回3)

正如在评论中所讨论的,复杂性是关于
O(k*log(n))
的,其中k是唯一项的数量,因此当k比n小时,这种方法工作得很好,并且在
k~n

def countuniquebs(A):
    n = len(A)
    t = A[0]
    l = 1
    count = 0
    while l < n - 1:
        r = n - 1
        while l < r:
            m = (r + l) // 2
            if A[m] > t:
                r = m
            else:
                l = m + 1
        count += 1
        if l < n:
            t = A[l]
    return count

print(countuniquebs([1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,5,5,5,5,5,5,5,5,5,5]))
def countuniquebs(A):
n=len(A)
t=A[0]
l=1
计数=0
而lt:
r=m
其他:
l=m+1
计数+=1
如果l
利用二进制搜索的工作代码(给定示例返回3)

正如在评论中所讨论的,复杂性是关于
O(k*log(n))
的,其中k是唯一项的数量,因此当k比n小时,这种方法工作得很好,并且在
k~n

def countuniquebs(A):
    n = len(A)
    t = A[0]
    l = 1
    count = 0
    while l < n - 1:
        r = n - 1
        while l < r:
            m = (r + l) // 2
            if A[m] > t:
                r = m
            else:
                l = m + 1
        count += 1
        if l < n:
            t = A[l]
    return count

print(countuniquebs([1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,5,5,5,5,5,5,5,5,5,5]))
def countuniquebs(A):
n=len(A)
t=A[0]
l=1
计数=0
而lt:
r=m
其他:
l=m+1
计数+=1
如果l
我不太可能称之为“使用二进制搜索”,但这种二进制分治算法在O(k*log(n)/log(k))时间内工作,这比重复的二进制搜索要好,而且永远不会比线性扫描差:

def countUniques(A, start, end):
    len = end-start
    if len < 1:
        return 0
    if A[start] == A[end-1]:
        return 1
    if len < 3:
        return 2
    mid = start + len//2
    return countUniques(A, start, mid+1) + countUniques(A, mid, end) - 1

A = [1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,3,4,5,5,5,5,5,5,5,5,5,5]
print(countUniques(A,0,len(A)))
def countUniques(A,开始,结束):
len=结束-开始
如果len<1:
返回0
如果A[start]==A[end-1]:
返回1
如果len<3:
返回2
中=开始+长//2
返回countUniques(A,开始,中间+1)+countUniques(A,中间,结束)-1
A=[1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,3,4,5,5,5,5,5,5]
打印(countUniques(A,0,len(A)))
我不太可能称之为“使用二进制搜索”,但这种二进制分治算法在O(k*log(n)/log(k))时间内工作,这比重复的二进制搜索要好,而且永远不会比线性扫描差:

def countUniques(A, start, end):
    len = end-start
    if len < 1:
        return 0
    if A[start] == A[end-1]:
        return 1
    if len < 3:
        return 2
    mid = start + len//2
    return countUniques(A, start, mid+1) + countUniques(A, mid, end) - 1

A = [1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,3,4,5,5,5,5,5,5,5,5,5,5]
print(countUniques(A,0,len(A)))
def countUniques(A,开始,结束):
len=结束-开始
如果len<1:
返回0
如果A[start]==A[end-1]:
返回1
如果len<3:
返回2
中=开始+长//2
返回countUniques(A,开始,中间+1)+countUniques(A,中间,结束)-1
A=[1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,3,4,5,5,5,5,5,5]
打印(countUniques(A,0,len(A)))

这不是递归的。但我不确定它是否有效,您永远不会更改
。它返回
5
在您的示例中,正确答案是3。它不是计算唯一值,而是计算查找第一个元素所需的二进制搜索的迭代次数。@Barmar是的,我说我在寻找迭代方法。我有固定的返回值。是的,我知道这是错误的,这就是我在这里发布的原因。似乎BS方法的复杂性是
O(klogn)
其中n是数组大小,k是唯一项的数量。当k与n相当时,时间变为O(nlogn)-肯定比线性扫描慢-这不是递归的。但我不确定它是否有效,您永远不会更改
。它返回
5
在您的示例中,正确答案是3。它不是计算唯一值,而是计算查找第一个元素所需的二进制搜索的迭代次数。@Barmar是的,我说我在寻找迭代方法。我有固定的返回值。是的,我知道这是错误的,这就是我在这里发布的原因。似乎BS方法的复杂性是
O(klogn)
其中n是数组大小,k是唯一项的数量。当k与n相当时,时间变为O(nlogn)-肯定比线性扫描慢