索引范围内的模糊重复

时间:2015-09-18 06:32:28

标签: python algorithm

以下是一位朋友被问到的面试问题。我们都难过了。声明如下:

  

考虑一个未排序的整数列表A。假设A的大小为n。进一步假设索引i处的元素具有值x。我们定义了两个术语:

     
      如果值A位于k中的任何一个,则
  • x在索引范围A[i-k], A[i-k+1],...,A[i-1],A[i+1],...,A[i+k]中有“重复”(即k是跨指标搜索的半径)

  •   如果A的任何元素位于d范围内,则{li>

    A的“值范围x-d, x-d+1,...,x,x+1,...,x+d重复”(即d为跨值搜索的半径)

      
     

在O(n)时间和O(k)空间中,我们想知道:

     
      
  1. A在索引范围k中是否有重复?

  2.   
  3. A索引范围k和值范围d是否重复?

  4.   

第一个很简单:我们从索引0走到n-1并保留一组我们见过的k个数字。如果我们在添加之前我们当前的数字已经在集合中,那么我们就有了重复数据。否则我们不会,并且我们删除集合中最旧的元素以为新的元素腾出空间。

第二个,我不知道。我可以想到O(nd)时间和O(k)空间中的解决方案:保持与第一个问题相同的设置,但是,当我们点击x时,检查{{1}之间的每个数字}和x-d。但我无法想象在空间或时间复杂度方面没有x+d的解决方案会是什么样子。我错过了什么?

2 个答案:

答案 0 :(得分:6)

您可以通过扩展第一种方法来完成第二部分。

不是将原始值存储在集合中,而是使用字典并存储除以d + 1的值(映射到实际值)。

重点是我们可以确定没有2个值可以位于同一个bin中(或者它们比d更接近)。

现在,当您扫描时,您需要检查垃圾箱中的可能碰撞以及两个相邻的垃圾箱。

所以这是O(3n)= O(n)运算和O(k)空间。

Python代码示例

def check_for_duplicate(A,d,k):
    D = {} # Stores the previous 2k entries 
    for i,a in enumerate(A):
        b = a // (d+1)
        for delta in [-1,0,1]:
            if b+delta in D and abs(D[b+delta] - a) <= d:
                return True
        old = i - 2 * k
        if old >= 0:
            del D[ A[old] // (d+1) ]
        D[b] = a
    return False

print check_for_duplicate(A=[8,14],d=5,k=2)

答案 1 :(得分:1)

所以它发生在我身上,你可以做到

part1 = false;
part2 = false;
for (index = i - k; index <= i + k, index++) {
  diff = ABS(A[index] - x);
  if (diff == 0) { part1 = true; }
  if (diff < d) { part2 = true; }
}

(不是在python中,但算法似乎已经足够了)让我知道如果我完全忽略了这一点,那就太晚了。