数组中重复的数字
题意:
在一个长度为n的数组里的所有数字都在0~n-1的范围内。数组中某些数字是重复的,但是不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。例如,如果输入长度为7的数组为{2,3,1,0,2,5,3},那么对于的输出是重复的数字2或者3。
题解:
首先是空间复杂度o(n),时间复杂度o(n)的算法。这个算法不足以拿到offer。直接开一个o(n)的arr辅助数组,并初始化为0,遍历numbers,每次把arr[numbers[i]]++。如果arr[numbers[i]]>=2,则说明numbers[i]重复了。直接返回便是。然后重点谈一下时间复杂度o(n),空间复杂度o(1)的算法。这个算法需要点思维。首先我们需要明白,如果该数组排好序,且没有重复的话那么numbers[i] = i,而现在这个有重复,那么会出现位置使得numbers[i]不等于i, 那么扫描numbers,当扫描到i时,如果numbers[i] != i 那么判断numbers[i] == number[numbers[i]]?如果等于的话那么就代表numbers[i]重复了,返回。如果不等于的话,就交换numbers[i]和numbers[numbers[i]],还原numbers[i]中的数字。建议模拟一下该算法。
java代码:
class Solution {
// Parameters:
// numbers: an array of integers
// length: the length of array numbers
// duplication: (Output) the duplicated number in the array number,length of
// duplication array is 1,so using duplication[0] = ? in implementation;
// Here duplication like pointor in C/C++, duplication[0] equal *duplication in
// C/C++
// 这里要特别注意~返回任意重复的一个,赋值duplication[0]
// Return value: true if the input is valid, and there are some duplications in
// the array number
// otherwise false
public boolean duplicate(int numbers[], int length, int[] duplication) {
if (length <= 1 || numbers == null) { //这个是必须要加的,如果如果没加的话offer有点难
return false;
}
for (int i = 0; i < length; i++) {
while(numbers[i] != i) {
if(numbers[i] == numbers[numbers[i]]) {
duplication[0] = numbers[i];
return true;
}
int temp = numbers[i];
numbers[i] = numbers[temp];
numbers[temp] = temp;
}
}
return false;
}
}
拓展:
这个算法是否也意味着,对于大小为n的数组,没有重复元素,value的范围从0~n-1。就可以用时间复杂度o(n),空间复杂度o(1)给他解决掉。这个点还是挺不错的。
如果有什么问题,或者有更加优秀的算法。欢迎留言,互相学习。