修改(?)二进制搜索

时间:2018-09-18 18:57:32

标签: python

我正在尝试解决一个问题,即在0(nlogn)的时间内找到列表中所有对数为k的对。

我首先对列表进行排序(我使用合并排序),然后对数组的每个元素x进行二进制搜索以查找(k-x)。这适用于常规列表,但是例如,如果我有一个类似[1,1,1,1]且k = 2的列表,我的代码将返回4而不是6。我想知道二进制搜索是否存在任何变体,从而允许为了上述事情发生。我尝试在Google上四处搜寻,但找不到任何能解决这个问题的东西。

作为参考,这是我的代码(我不包括合并排序,因为它不相关)

def binary_search(alist, item):
    if len(alist)==0:
       return False
    else:
       mid=len(alist)//2
       if alist[mid]==item:
          return True
       else:
          if item< alist[mid]:
            return binary_search(alist[:mid], item)
          else:
            return binary_search(alist[mid+1:], item)

def find_pairs(alist, k):
    count=0
    for i in range(len(alist)):
            if binary_search(alist,(k-alist[i])):                        
                    count+=1                       

    return(count)

2 个答案:

答案 0 :(得分:0)

Since you want to do it with Binary Search:

  1. Take unique values from the list and sort
  2. Create an auxiliary list which representing counts of those values.
  3. Take first element, mark it x, binary search for (k-x) in the remaining list. If found, add aux[index(x)]*aux[index(k-x)] to result.

Additional step: For the case that you have mentioned, if k is even, look for k/2. If present, add Combination(aux[index(k/2)], 2) to the result.

All this should be within nlogn. Also, you can achieve the same without much hassle using Python Dictionaries.

答案 1 :(得分:0)

I think you can do this in O(n) time and O(n) space.

def num_pairs(arr, k):
    counts = Counter(arr)
    total = 0
    for item, count in counts.items():
        diff = k - item
        if diff in counts and (diff < item or (diff==item and count>1)):
            if diff == item:
                total += (count*(count-1))//2
            else:
                total += count*counts[diff]
    return total

Here we make a mapping of each number to the number of times it occurs in the input. For each entry we look up the complement in mapping, and can then compute the number of such pairs using arithmetic.