给定一个整数列表,如何最好地找到一个不在列表中的整数?该列表可能非常大,并且整数可能很大(即BigIntegers,而不仅仅是32位int)。如果有任何区别,列表“可能”已排序,即99%的时间它将被排序,但我不能依赖始终排序。要澄清的是,给定列表{0,1,3,4,7},可接受解决方案的示例为-2、2、8和10012,但如果有一种算法可以在不需要对整个列表进行排序的情况下找到最小的非负解(即2),我更愿意使用该算法。
n
,然后您就知道n+1
不在列表中。startIndex
变量跟踪相关数字的起始位置:public static int GetSmallest(int[] items) {
int startIndex = 0;
int result = 0;
int i = 0;
while (i < items.Length) {
if (items[i] == result) {
result++;
i = startIndex;
} else {
if (items[i] < result) {
if (i != startIndex) {
int temp = items[startIndex];
items[startIndex] = items[i];
items[i] = temp;
}
startIndex++;
}
i++;
}
}
return result;
}
我在正确性和性能方面均获得了100%的分数,你应该使用快速排序,其复杂度为N log(N)。这是你需要的内容...
public int solution(int[] A) {
if (A != null && A.length > 0) {
quickSort(A, 0, A.length - 1);
}
int result = 1;
if (A.length == 1 && A[0] < 0) {
return result;
}
for (int i = 0; i < A.length; i++) {
if (A[i] <= 0) {
continue;
}
if (A[i] == result) {
result++;
} else if (A[i] < result) {
continue;
} else if (A[i] > result) {
return result;
}
}
return result;
}
private void quickSort(int[] numbers, int low, int high) {
int i = low, j = high;
int pivot = numbers[low + (high - low) / 2];
while (i <= j) {
while (numbers[i] < pivot) {
i++;
}
while (numbers[j] > pivot) {
j--;
}
if (i <= j) {
exchange(numbers, i, j);
i++;
j--;
}
}
// Recursion
if (low < j)
quickSort(numbers, low, j);
if (i < high)
quickSort(numbers, i, high);
}
private void exchange(int[] numbers, int i, int j) {
int temp = numbers[i];
numbers[i] = numbers[j];
numbers[j] = temp;
}
除非它已经排序,否则您将不得不进行线性搜索,逐个查找匹配项,直到找到匹配项或到达列表末尾。如果您可以保证已排序,则始终可以使用二进制搜索的数组方法或自己编写二进制搜索。
或者像Jason提到的那样,总是有使用Hashtable的选项。
除非您100%确定列表已排序,否则最快的算法仍然必须至少查看列表中的每个数字一次,以至少验证数字不在列表中。
有几种方法:
在列表中找到最大的整数并将其存储在x中。 x + 1不会在列表中。使用min()和x-1也是一样的。
当N是列表的大小时,分配一个大小为(N+31)/32
的int数组。对于列表中的每个元素,在数组索引i/32
处设置位v&31
(其中v
是元素的值)的整数。忽略i/32 >= array.length
的值。现在搜索第一个数组项“!= 0xFFFFFFFF”(对于32位整数)。
如果您无法保证它已排序,则最佳时间效率为O(N),因为您必须查看每个元素以确保您的最终选择不在其中。那么问题就是:
Chris Doggett的解决方案是找到最大值并加1,既具有O(N)的时间效率,又具有空间效率(O(1)的内存使用)。
如果您只想要可能的最佳答案,那么这是一个不同的问题。