繁体   English   中英

在数组中查找缺少的元素

[英]Finding Missing Element in an Array

我有一个有趣的问题,给出了两个排序的数组:

a有n个元素,b有n-1个元素。

b除了一个元素之外的所有元素都缺失了。

如何在O(log n)时间内找到该元素?

我试过这段代码:

def lostElements2(a, b):
    if len(a)<len(b):
        a, b = b, a

    l, r = 0, len(a)-1

    while l<r:
        m = l + (r-l)//2

        if a[m]==b[m]:
            l = m+1
        else:
            r = m - 1

    return a[r]


print(lostElements2([-1,0,4,5,7,9], [-1,0,4,5,9]))  

我不知道我应该在函数中返回什么,如果它是[l],[r]?

我得知函数内部的逻辑应该如何:如果两个数组的中间值匹配,则意味着,b直到中点与a相同,因此缺少的元素必须在mid的右边。

但我无法创建最终解决方案,何时应该停止循环以及应该返回什么? 它如何保证[l]或[r]确实是缺失的元素?

这个问题的原理很简单,细节很难。

你已经安排了数组a是更长的数组。 好,这简化了生活。 现在你需要返回的值, a在第一位置的值a从的值不同b

现在您需要确保处理以下边缘情况。

  1. 不同的值是最后一个(即在只有数组a具有值的位置)。
  2. 不同的价值是第一个。 (对于这种情况,二进制搜索算法很容易搞砸。
  3. 有一个相同的运行。 那是a = [1, 1, 2, 2, 2, 2, 3]b = [1, 2, 2, 2, 2, 3] - 当你在中间着陆时,值匹配的事实会误导您!

祝好运!

lr的点应该是l始终是列表相等的位置,而r总是它们不同的位置。 IE浏览器。 a[l]==b[l]a[r]!=b[r]

代码中唯一的错误是将r更新为m-1而不是m 如果我们知道a[m]!=b[m] ,我们可以安全地设置r=m 但将其设置为m-1可能会a[r]==b[r] ,这会破坏算法。

def lostElements2(a, b):
    if len(a) < len(b):
        a, b = b, a
    if a[0] != b[0]:
        return a[0]

    l, r = 0, len(a)-1
    while l < r:
        m = l + (r-l)//2
        if a[m] == b[m]:
            l = m+1
        else:
            r = m # The only change
    return a[r]

(正如@btilly所指出的,如果我们允许重复的值,这个算法会失败。)

从@btilly编辑

为了解决这个潜在的缺陷,如果值相等,我们搜索具有相同值的范围。 为此,我们以1号,2号,4号,8号等步长向前走,直到值切换,然后进行二分查找。 并向后走同样的道路。 现在寻找每个边缘的差异。

该搜索所需的努力是O(log(k)) ,其中k是重复值的长度。 所以我们现在用搜索替换O(log(n))查找。 如果在该搜索的长度上存在上限K ,则表示总运行时间。 O(log(n)log(K)) 这使得最坏情况下的运行时间为O(log(n)^2) 如果K接近sqrt(n) ,那么实际上很容易碰到最坏的情况。

我在评论中声称,如果最多K元素重复超过K次,则运行时间为O(log(n)log(K)) 进一步分析,这种说法是错误的。 如果K = log(n)并且log(n)运行长度sqrt(n)被放置以命中搜索的所有选择,那么你得到运行时间O(log(n)^2)而不是O(log(n)log(log(n)))

但是,如果最多log(K)元素重复超过K次,那么你得到的运行时间为O(log(n)log(K)) 对于大多数情况来说,哪个应该足够好。 :-)

您的代码不处理缺少元素是索引m本身的情况。 后面的if / else子句将始终移动缺少元素的边界,使其不包括m。

您可以通过添加额外的检查来解决此问题:

if a[m]==b[m]:
    l = m+1
elif m==0 or a[m-1]==b[m-1]:
    return a[m]
else:
    r = m - 1

另一种方法是存储m的最后一个值:

last_m = 0
...
else:
    last_m = m
    r = m - 1
...
return a[last_m]

哪会导致它在上次检测到不匹配时返回。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM