找到第一个独特元素

时间:2013-02-23 21:57:32

标签: algorithm sorting search data-structures time-complexity

我在采访中遇到了这个问题,我无法回答。 您必须在数组中找到第一个唯一元素(整数)。 例如:

3,2,1,4,4,5,6,6,7,3,2,3

然后,唯一元素为1, 5, 7,并且1的第一个唯一元素。

所需的解决方案:

  

O(n)时间复杂性。

     

O(1)空间复杂性。

我试着说:

使用Hashmaps,Bitvector ......但它们都没有空间复杂度O(1)。

有人能用空间O(1)告诉我解决方案吗?

4 个答案:

答案 0 :(得分:10)

这是一个非严格的证据,证明它是不可能的: 众所周知,当使用O(1)空间时,重复检测不能比O(n * log n)更好。假设当前问题在O(n)时间和O(1)存储器中是可解的。如果我们得到第一个非重复数的索引'k'为0以外的任何值,我们知道k-1是重复的,因此再一次扫描数组我们可以得到它的重复,使重复检测为O( n)锻炼。

同样,它并不严谨,我们可以进入最差的案例分析,其中k总是为0.但它可以帮助你思考并说服面试官不太可能。

http://en.wikipedia.org/wiki/Element_distinctness_problem说: 在大小为n的多集中出现超过n / k次的元素可以在时间O(n log k)中找到。这里k = n,因为我们希望元素出现不止一次。

答案 1 :(得分:0)

我认为这是不可能的。这不是证据,而是猜测的证据。我的推理如下......

首先,你说元素的价值没有约束(它们可以是负数,0或正数)。其次,只有O(1)个空格,因此我们不能存储超过固定数量的值。因此,这意味着我们必须仅使用比较来解决这个问题。此外,我们不能对数组中的值进行排序或交换,因为我们会丢失唯一值的原始排序(并且我们无法存储原始排序)。

考虑一个所有整数都是唯一的数组:

1, 2, 3, 4, 5, 6, 7, 8, 9, 10

为了在这个数组上返回正确的输出1而不重新排序数组,我们需要将每个元素与所有其他元素进行比较,以确保它是唯一的,并以相反的顺序执行此操作,所以我们可以检查最后的第一个独特元素。这需要O(n^2)O(1)空格进行比较。

如果有人找到解决方案,我会删除这个答案,我欢迎任何关于将其变成更严格证据的指示。

答案 2 :(得分:0)

注意:这在一般情况下无效。请参阅下面的推理。

最初的想法

也许在O(n)时间和O(1)额外空间中存在解决方案。

可以在O(n)时间内构建堆。请参阅Building a Heap

所以你向后构建了堆,从数组的最后一个元素开始,并将最后一个位置作为根。构建堆时,请跟踪最近没有重复的项目。

这假定在堆中插入项时,您将遇到堆中已存在的任何相同项。我不知道我是否可以证明这一点。 。

假设上述情况属实,那么当您构建堆时,您知道哪个项是第一个非重复项。

为什么它不起作用

在适当位置构建堆的算法从数组的中点开始,并假设超出该点的所有节点都是叶节点。然后它向后工作(朝向项目0),将项目筛选到堆中。该算法不会检查任何特定顺序中的最后n / 2个项目,并且当项目被筛选到堆中时,顺序会更改。

结果,我们能做的最好的事情(即使那时我不确定我们能否可靠地做到)只有在数组的前半部分出现时才会找到第一个非重复的项目。

答案 3 :(得分:0)

OP的问题原文没有提到数字的限制(虽然后者的加数可以是负数/正数/零)。在这里,我假设还有一个条件:

  

数组中的数字都小于数组长度和   是非负数。

然后,给出一个O(n)时间,O(1)空间解决方案是可能的,并且看起来像是一个面试问题,并且OP中给出的测试用例符合上述假设。

解决方案:

for (int i = 0; i < nums.length; i++) {
  if (nums[i] != i) {
    if (nums[i] == -1) continue;
      if (nums[nums[i]] == nums[i]) {
        nums[nums[i]] = -1;
      } else {
        swap(nums, nums[i], i);
        i--;
      }
    }
  }
}

for (int i = 0; i < nums.length; i++) {
  if (nums[i] == i) {
    return i;
  }
} 

这里的算法是将原始数组视为存储桶排序中的存储桶。将数字放入其桶中,如果超过两次,则将其标记为-1。使用另一个循环来查找具有nums [i] == i

的第一个数字