题目:数组中重复的数字
描述
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任一一个重复的数字。
例如,如果输入长度为7的数组[2,3,1,0,2,5,3],那么对应的输出是2或者3。存在不合法的输入的话输出-1。
思路分析:在进行具体思考时,应该注意两点,当输入的数组为空时或者输入的数组不重复。这两点问题应该另外分析。
首先可以将数组进行排序,将排好序的数组,从开头进行遍历,在遍历的同时,记录好当前位置与之前位置的数,进行比较,如果相等,则输出该数,否则判断下一位数字。
具体思路分析:当输入的数组长度为7,具体数值为[2,3,1,0,2,5,3]时,进行以下分析:
2 | 3 | 1 | 0 | 2 | 5 | 3 |
调用sort函数,对数组进行排序 | ||||||
0 | 1 | 2 | 2 | 3 | 3 | 5 |
排序完成后,进行遍历操作,将当前位置与之前位置的两个数进行比较,相等的话,输出该数,经过比较,输出的数字为2。
实现的具体C++代码如下所示:
class Solution { public: /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param numbers int整型vector * @return int整型 */ int duplicate(vector<int>& numbers) { // write code here if(numbers.size()==0) { return -1; } sort(numbers.begin(),numbers.end()); for(int i=0;i<numbers.size()-1;) { if(numbers[i]==numbers[i+1]) { return numbers[i]; } i++; } return -1; } };
该算法的时间复杂度为O(n)。
思路分析:从头到尾遍历数组,当扫描到下标位为i的位置时,比较数字m是否等于i,如果是,接着扫描下一个数字,如果不是,则拿它和下标位m的数字比较,如果相等,就找到了第一个重复数字(该数字在下标i和m位置同时出现了),如果不相等,就把第i个数字和第m个数字交换,重复这个比较。
具体思路如下表所示:
0 | 1 | 2 | 3 | 4 | 5 | 6 |
2 | 3 | 1 | 0 | 2 | 5 | 3 |
第一次
0 | 1 | 2 | 3 | 4 | 5 | 6 |
1 | 3 | 2 | 0 | 2 | 5 | 3 |
第二次
0 | 1 | 2 | 3 | 4 | 5 | 6 |
1 | 3 | 2 | 0 | 2 | 5 | 3 |
第三次
0 | 1 | 2 | 3 | 4 | 5 | 6 |
3 | 1 | 2 | 0 | 2 | 5 | 3 |
第四次
0 | 1 | 2 | 3 | 4 | 5 | 6 |
0 | 1 | 2 | 3 | 2 | 5 | 3 |
第五次
当判断到4的时候,下标4代表的数字为2,跟下标为2代表的数字相同,即数字2为重复数字。
该C语言代码如下所示:
/** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param numbers int整型一维数组 * @param numbersLen int numbers数组长度 * @return int整型 */ int duplicate(int* numbers, int numbersLen ) { // write code here if(numbers == NULL || numbersLen <= 0)//非正常情况 return -1; int i = 0; for(;i < numbersLen;i++){ if(numbers[i] < 0 || numbers[i] >= numbersLen)//题目要求 return -1; } for(i = 0; i < numbersLen;i++){ while(numbers[i] != i){ if(numbers[i] == numbers[numbers[i]]) return numbers[i]; int tmp = numbers[i];//数字交换 numbers[i] = numbers[tmp]; numbers[tmp] = tmp; } }。 return -1; }
时间复杂度O(N),空间复杂度O(1)。