我在采访中遇到了这个问题,我无法回答。 您必须在数组中找到第一个唯一元素(整数)。 例如:
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)告诉我解决方案吗?
答案 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)
数组中的数字都小于数组长度和 是非负数。
然后,给出一个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
的第一个数字