找到两个数字桶之间的最短距离

时间:2016-11-29 16:26:49

标签: c++ algorithm distance intersection euclidean-distance

我有两个数字桶(无序,1维数据结构),我想计算两个桶中任何元素之间的最小距离。有没有办法找到O(1)中来自不同桶的任何数字之间的最短距离?什么是我最好的选择?

Input
[B1] 1, 5, 2, 347, 50
[B2] 21, 17, 345

Output
2 // abs(347 - 345)

编辑

  • 我希望有比插入更多的查找
  • 任何桶中最小和最大元素之间的距离小于10 ^ 5
  • 任何存储桶中的元素数量少于10 ^ 5
  • 水桶中的数字是"几乎"已排序 - 这些是事件的时间戳。可能不到1%的桶中的元素乱序
  • 桶中的元素数量很少,但我需要以2k / sec的平均速率查找,并定期删除过时的桶并用新桶替换它们,因此我希望我的查找位于O(1)

previous question edition中了解我为什么需要这个和我想到的。

7 个答案:

答案 0 :(得分:1)

这是我的尝试:对每个桶进行排序,然后将它们合并,以便跟踪沿途的最小距离:O(n+2.n/2.ln(n/2)) = O(n.ln(n))

sort buk1
sort buk2
min = INT_MAX
last = some value
do
    if top(buk1) > top(buk2)
        min = min(min, abs(top(buk1) - last))
        last = top(buk1)
        pop(buk1)
    else
        min = min(min, abs(top(buk2) - last))
        last = top(buk2)
        pop(buk2)
while !empty(buk1) and !empty(buk2)

答案 1 :(得分:1)

总共有n个数字 1.用二进制编写所有数字。 ==> O(n)
2.根据是B1还是B2,在每个数字中附加0或1。 ==> O(n)
3.嘲笑他们,忽略第一位。平均==> O(n log n)个 4.对于整个列表,迭代排序顺序。对于每两个相邻的数字uv,如果它们来自B1或B2,则忽略。
否则,只要tmp <-- abs(u-v)设置tmp > abs(u-v)。 因此,tmp是目前为止在相邻数字内的最小距离 最后的tmp就是答案。 ==> O(n)

总计:==> O(n log n)平均

答案 2 :(得分:1)

O(1)当然是不可能的。

一些伪代码,我将其作为起点:

sort(B1)
sort(B2)

i1 = 0
i2 = 0

mindist = MAX_INT

// when one of the buckets is empty, we'll simply return MAX_INT.
while(i1 < B1.size() && i2 < B2.size())
    t = B1[i1] - B2[i2]
    mindist = min(mindist, abs(t))
    if t > 0 
        i2 ++
    else
        i1 ++

return mindist

至少那是O(n log n),因为它在开头的排序中占主导地位。如果您的存储桶已经排序,则可以使用O(n)。

修改

在新信息之后,元素几乎已经排序,我建议在插入时对它们进行实际排序。使用二进制搜索的插入排序不是最适合这种情况的。只需附加新元素并将其交换,直到它适合。通常它不会掉期而且对于1%,你需要互换,99%的时间它只有一个。最坏的情况复杂度为O(n),但平均值几乎为O(1)。

如果您考虑为所有存储桶对预先计算mindist,则必须存储i1i2以及mindist。假设B1是存储桶,您可以在其中追加新元素。您可以对其进行排序并缩小i2,直到它为0B2[i2] < B1[i1]。由于元素是时间戳,因此大多数情况下最多只能执行一个步骤。然后再次运行while循环,通常只会执行一个步骤。因此k桶的计算复杂度为O(k),存储器复杂度为O(k ^ 2)。

答案 3 :(得分:1)

为每个存储桶创建一个10 ^ 5个元素的位向量。跟踪最小距离(最初10 ^ 5,直到两个桶都是非空的)。

现在,假设您正在向其中一个存储桶添加元素x。执行以下操作:

1. Set the bit x of the same bucket.
2. Check whether the other bitvector has any set elements within min_distance-1 of x
3. Update min_distance as appropriate

运行时间:在插入O(min_distance)时,技术上是O(1),因为min_distance是上限的。在轮询它的O(1)因为你刚刚返回min_distance。

编辑如果元素的上限不是10 ^ 5,而只是最小值和最大值之间的距离,则需要修改但仍然有效。如果这很重要,我可以详细说明必要的变化。

答案 4 :(得分:1)

将您的存储桶插入两次Y-fast尝试(https://en.wikipedia.org/wiki/Y-fast_trie)。搜索最近的继任者或前任是O(log log M),其中M是范围(实际上是最大元素,但我们可以抵消),在您的情况下,它将限制在大约四个操作。

由于您将存储最近的差异,因此查找将为O(1)(除非您每次都获得完整的存储桶而不是不断更新),而每个元素的插入,删除和更新将为O(log log M)

答案 5 :(得分:0)

我喜欢Dave Galvin的想法,略有修改:

设maxV为元素的最大数量maxV = max(bucket1.size,bucket2.size)

1。构建两个数组,每个数组的大小为maxV。填写他们:

for (j=0 to bucket1.size)
    array1(bucket1(j)) = bucket1(j)
for (j=0 to bucket2.size)
        array2(bucket2(j)) = bucket1(j)

现在对数组进行排序。数组中的其余元素为0。

2。现在使用两个迭代器,每个数组一个:

it1 = array1.begin
it2 = array2.begin
while (it1 == 0)
   ++it1
while (it2 == 0)
   ++it2
minDist = abs(it1-it2)
while (it1 != array1.end && it2 != array2.end)
{   //advance until overpass the other
    while (it1 <= it2 && it1 != array1.end)
        ++it1
        if (it1 > 0)
            check minDist between it1, it2
    while (it2 <= it1 && it2 != array2.end)
        ++it2
        if (it2 > 0)
            check minDist between it1, it2
    if (it1 = it2)
        //well, minDist = 0
        return now
}

步骤1是O(n)。步骤2也是O(n)。我不知道这是否比为大桶或短桶分拣铲斗更有效。

答案 6 :(得分:0)

考虑为两个列表中的每个数字预先计算答案,并将它们存储为数组。使用列表中每个数字的下标,并使用它下标到数组中包含差异的位置。

这给了O(1)查找。