九、一道有趣的GOOGLE面试题
问题的数学性描述:
一个大小为n的数组,里面的数都属于范围[0,
n-1],有不确定的重复元素,找到至少一个重复元素,要求O(1)空间和O(n)时间。
哈希表可以在遍历数组一次的情况下找到重复元素,时间复杂度也为O(n),但是空间复杂度不能降为O(1),所以不适合这道题
而基数排序的时间和空间复杂度刚好符合题目要求
1.基数排序查找重复元素示例
下面以2,4,1,5,7,6,1,9,0,2这十个数为例,展示下如何用基数排序来查找重复元素。
下标 0 1 2 3 4 5 6 7 8 9
数据 2 4 1 5 7 6 1 9 0 2
(1)由于第0个元素a[0]
等于2不为0,故交换a[0]与a[a[0]]即交换a[0]与a[2]得:
下标 0 1 2 3 4 5 6 7 8 9
数据 1 4 2 5 7 6 1 9 0 2
(2)由于第0个元素a[0]
等于1不为0,故交换a[0]与a[a[0]]即交换a[0]与a[1]得:
下标 0 1 2 3 4 5 6 7 8 9
数据 4 1 2 5 7 6 1 9 0 2
(3)由于第0个元素a[0]
等于4不为0,故交换a[0]与a[a[0]]即交换a[0]与a[4]得:
下标 0 1 2 3 4 5 6 7 8 9
数据 7 1 2 5 4 6 1 9 0 2
(4)由于第0个元素a[0]
等于7不为0,故交换a[0]与a[a[0]]即交换a[0]与a[7]得:
下标 0 1 2 3 4 5 6 7 8 9
数据 9 1 2 5 4 6 1 7 0 2
(5)由于第0个元素a[0]
等于9不为0,故交换a[0]与a[a[0]]即交换a[0]与a[9]得:
下标 0 1 2 3 4 5 6 7 8 9
数据 2 1 2 5 4 6 1 7 0 9
(6)由于第0个元素a[0]
等于2不为0,故交换a[0]与a[a[0]]即交换a[0]与a[2],但a[2]也为2与a[0]相等,因此我们就找到了一个重复的元素——2。
下标 0 1 2 3 4 5 6 7 8 9
数据 2 1 2 5 4 6 1 7 0 9
Pasted from:
<[http://blog.csdn.net/morewindows/article/details/8204460]{.ul}>
2.算法
Radixsort方法,这个方法满足要求,但是只能查找到一个重复元素
int Radixsort(int a[], int n)
{
int i;
for (i = 0; i < n; i++)
{
while (i != a[i])
{
if (a[i] == a[a[i]])
return a[i];
Swap(&a[i], &a[a[i]]);
}
}
return NO_REPEAT_FLAG;
}
FindRepeatNumberInArray方法,标记查到的数,再次查到就说明作为索引的数重复了
int FindRepeatNumberInArray(int * a, int n)
{
for (int i = 0; i < n; i++)
{
//每查到一个数就加n作为标记,如果后面的数的值有一个再查到了这个数,这个时候这个数是大于n的,就说明这个值跟之前某个数重复
int nRepeatIndex = a[i] >= n ? a[i] - n : a[i];
if (a[nRepeatIndex] >= n)
return nRepeatIndex;
else
a[nRepeatIndex] += n;
traverse(a, n);
}
return NO_REPEAT_FLAG;
}
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!