给定无序的整数列表,返回列表中不存在的值

时间:2012-03-15 20:31:34

标签: c algorithm

我遇到了一个我在工作中遇到的算法问题但是却无法找到令人满意的解决方案。我浏览了这个论坛,而我最接近同一问题的是How to find a duplicate element in an array of shuffled consecutive integers?

我有一个N个整数元素的列表,它可以包含元素1-M(M> N),而且列表是未排序的。我想要一个将此列表作为输入的函数,并返回列表中不存在的1-M范围内的值。该列表不包含重复项。我希望得到一个o(N)解决方案,而不使用额外的空间 更新:功能无法更改原始列表L

例如N = 5 M = 10 列表(L):1,2,4,8,3  然后f(L)= 5 说实话,我不在乎它是否返回5以外的元素,只要它符合上述约束

到目前为止,我提出的唯一解决方案是使用额外的M元素数组。遍历输入列表并将相应的数组元素设置为1(如果列表中存在)。然后再次遍历此列表并返回值为0的第一个元素的索引。如您所见,这会使用额外的o(M)空间并具有复杂度2 * o(N)。 任何帮助我们都会感激。

感谢大家的帮助。堆栈溢出社区绝对是非常有用的。 为每个人提供一些我正在努力解决的问题的背景。 我有一组M令牌,我给一些客户(每个客户一个)。当客户完成令牌后,他们就会回到我的堆里。正如您所看到的那样,我给客户端一个令牌进行排序。
所以M = 3个代币
client1:1< 2,3>
client2:2< 3>
client1返回:1< 1,3>
客户3:3< 1>
现在的问题是给client4令牌1.我可以在这个阶段给客户端4令牌2并对列表进行排序。不确定这是否有帮助。在任何情况下,如果我想出一个很好的清洁解决方案,我一定会发布它 刚刚意识到我可能会困扰每个人。我被叫时,我没有免费令牌列表。我可以静态维护这样的列表,但我宁愿不

4 个答案:

答案 0 :(得分:3)

你可以分而治之。基本上给定范围1..m,以m / 2作为枢轴进行快速排序样式交换。如果前半部分中的元素少于m / 2,则缺少数字并迭代找到它。否则,下半场会有一个丢失的号码。复杂度:n + n / 2 + n / 4 ... = O(n)

def findmissing(x, startIndex, endIndex, minVal, maxVal):
    pivot = (minVal+maxVal)/2
    i=startIndex
    j=endIndex
    while(True):
        while( (x[i] <= pivot) and (i<j) ):
            i+=1
        if i>=j:
            break
        while( (x[j] > pivot) and (i<j) ):
            j+=1
        if i>=j:
            break
        swap(x,i,j)
     k = findlocation(x,pivot)
     if (k-startIndex) < (pivot-minVal):
         findmissing(x,startIndex, k, minVal, pivot)
     else:
         findmissing(x, k+1, endIndex, pivot+1, maxVal)

我没有实现最终条件,我会留给你。

答案 1 :(得分:1)

你能做点计数吗?创建一个大小(M-1)的数组,然后遍历列表一次(N)并将在i-1索引的数组元素更改为1。在通过N循环一次后,搜索0->(M-1),直到找到第一个数值为零的数组。

我应该是O(N + M)。

大小为(M-1)的数组L:[0 = 0,1 = 0,2 = 0,3 = 0,4 = 0,5 = 0,6 = 0,7 = 0,8 = 0, 9 = 0]

在循环N个元素之后:[0 = 1,1 = 1,2 = 1,3 = 1,4 = 0,5 = 0,6 = 0,7 = 1,8 = 0,9 = 0]

搜索数组0-&gt;(M-1)发现索引4为零,因此5(4 + 1)是不在L中的第一个整数。

答案 2 :(得分:1)

您可以拥有O(N)时间和空间。你可以确定1..N + 1中有一个缺席元素,所以制作一个N + 1个元素的数组,并忽略大于N + 1的数字。

如果M与N相比较大,比如M> 2N,则在1..M中生成一个随机数,并在O(N)时间O(1)空间中检查它是否不在列表中。您在单次通过中找到解的概率至少为1/2,因此(几何分布)预期通过次数是常数,平均复杂度为O(N)。

如果M是N + 1或N + 2,请使用here描述的方法。

答案 3 :(得分:1)

阅读更新后我猜你正在复杂化。首先让我列出你从问题中得到的东西

  • 你需要向客户提供一个令牌,无论其订单如何,引用你原来的帖子
  

例如N = 5 M = 10列表(L):1,2,4,8,3然后f(L)= 5要   诚实,我不在乎它是否返回5以外的元素,只是这么久   因为它符合上面的限制

  • 其次,您已经在维护“M”代币列表
  • 客户端正在获取令牌,并在使用后将其返回给您

鉴于这两点,为什么不实施 TokenPool

  • 根据队列
  • 实施您的M列表
  • 每当客户端请求令牌时,从队列中获取令牌,即将其从队列中删除。通过这种方法,您的队列将始终保留那些未给出的令牌。你正在做O(1)
  • 每当客户完成令牌后,他都会将其返还给您。将其添加回队列。再次O(1)。

在整个实现中,您不必遍历任何列表。您所要做的就是生成令牌并插入队列中。