我从codefights解决了这个问题:
注意:编写具有O(n)时间复杂度和O(1)额外空间复杂度的解决方案,因为这是您在真实访谈期间要求做的事情。
给定一个仅包含1到a.length范围内的数字的数组a,找到第二个匹配项具有最小索引的第一个重复数字。换句话说,如果有多于1个重复的数字,则返回第二次出现的索引小于另一个出现的第二次出现的索引的数量。如果没有这样的元素,则返回-1。
int firstDuplicate(int[] a) {
HashSet z = new HashSet();
for (int i: a) {
if (z.contains(i)){
return i;
}
z.add(i);
}
return -1;
}
我的解决方案通过了所有测试。但是我不明白我的解决方案如何满足O(1)额外的空间复杂度要求。哈希表的大小与输入成正比,因此我认为它是O(n)空间复杂度。 codefights是不是错误地测试了我的算法,还是我误解了什么?
答案 0 :(得分:3)
您的代码没有O(1)辅助空间复杂性,因为如果给定所有不同元素的数组,该哈希集可以增长到n。
我的猜测是,在线测试基础架构没有检查内存使用情况或以其他方式检查内存使用情况。如果你想要满足空间限制,你需要回过头来尝试以不同的方式解决问题。
作为提示,请考虑重新排序数组元素。
答案 1 :(得分:1)
如果您能够修改incomming数组,则可以使用O(n)
时间复杂度修复问题,并且不使用外部内存。
public static int getFirstDuplicate(int... arr) {
for (int i = 0; i < arr.length; i++) {
int val = Math.abs(arr[i]);
if (arr[val - 1] < 0)
return val;
arr[val - 1] = -arr[val - 1];
}
return -1;
}
答案 2 :(得分:0)
这在技术上是不正确的,原因有两个。
首先,根据数组中的值,当int
成为Integer
并添加到HashSet
时,可能会有开销。
其次,虽然附加内存主要是与HashSet
相关的开销,但该开销与集合的大小成线性比例。 (请注意,我不计算其中的元素,因为它们已经存在于数组中。)
通常,通过设置可以使用的内存量限制来测试这些内存约束。像这样的解决方案我希望低于上述阈值。