如题:
题目描述
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字
是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数
组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
方法由很多,四种,显然,排序法和哈希查找法都可以。第三种方法比较巧妙,利用了题目中数字都在0~n-1这个限制,第四种方法,也就是暴力遍历法,能解决问题,但不推荐。
方法1:排序法:使用快速排序,平均时间复杂度为O(nlogn),最坏O(n^2),需要修改原数组,和暴力遍历法相同,。
方法2:哈希查找法:将数组中元素依次加入hash表中,遇到重复的元素即可返回,时间复杂度为O(1),但需使用额外O(n)的空间。
方法3:方法三就比较巧妙了,这也是剑指推荐的方法,时间复杂度为O(n),剑指上很多题目,其实都是可以通过查找规律,找到更好的方法。这道题,数组长度为n,数字范围为0~n-1,显然,如果不重复,排好序后,每个元素都应该存在自己值对应的下标中。因此,我们遍历从0遍历数组,将遍历到的值,替换到其对应下标所在位置,如果已经存在,说明重复,返回即可。
方法4:暴力遍历法,只有在无路可走的情况下,方可出此下策,时间复杂度为O(n^2)。双重循环,对于每一个元素,遍历其后的数组,查找相同元素。
方法2,3是比较容易想到的,有经验的话,看到数字范围0~n-1也比较容易想到第三种,新手可能选择第四种。下面是c++语言的版本方法3。
class Solution {
public:
// Parameters:
// numbers: an array of integers
// length: the length of array numbers
// duplication: (Output) the duplicated number in the array number
// Return value: true if the input is valid, and there are some duplications in the array number
// otherwise false
bool duplicate(int numbers[], int length, int* duplication) {
int i, val;
//特殊情况处理
if (length < 2)
return false;
*duplication = -1;
//遍历数组
for (i = 0; i < length;)
{
if (numbers[i] == i)
i++;
else if (numbers[i] == numbers[numbers[i]])
{
*duplication = numbers[i];
return true;
}
else
{
val = numbers[numbers[i]];
numbers[numbers[i]] = numbers[i];
numbers[i] = val;
}
}
return false;
}
};
=============================================================================================
Linux应用程序、内核、驱动,后台开发交流讨论群(745510310),感兴趣的同学可以加群讨论、交流、资料查找等,前进的道路上,你不是一个人奥^_^。