标签:统计 inpu poi 输入 input ret == OLE other
题目要求:在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
1 public class Solution { 2 // Parameters: 3 // numbers: an array of integers 4 // length: the length of array numbers 5 // duplication: (Output) the duplicated number in the array number,length of duplication array is 1,so using duplication[0] = ? in implementation; 6 // Here duplication like pointor in C/C++, duplication[0] equal *duplication in C/C++ 7 // 这里要特别注意~返回任意重复的一个,赋值duplication[0] 8 // Return value: true if the input is valid, and there are some duplications in the array number 9 // otherwise false 10 public boolean duplicate(int numbers[],int length,int [] duplication) { 11 } 12 }
思路一:最好的解法
此大法利用了哈希的特性,但不需要额外的存储空间。 因此时间复杂度为O(n),不需要额外空间!
因为列表总共有n个元素,所有元素可能取到的元素有0~n-1,共n种。如果不存在重复的数字,那么排序后数字i将会出现在下标为i的位置。现在让我们重新扫描数组,
1 public class Solution { 2 public boolean duplicate(int numbers[],int length,int [] duplication) { 3 //考虑特殊情况,并判断数组是否合法(每个数都在0~n-1之间) 4 if(length<=0||numbers==null) return false; 5 for(int i=0;i<length;i++){ 6 if(numbers[i]<=0||numbers[i]>length-1) 7 return false; 8 } 9 //关键代码来了 10 for(int i=0;i<length;i++){ 11 while(numbers[i]!=i){ 12 if(numbers[i]==numbers[numbers[i]]){ 13 duplication[0] = numbers[i]; 14 return true; 15 } 16 //交换numbers[i]和numbers[numbers[i]] 17 int temp = numbers[i]; 18 numbers[i] = numbers[temp]; 19 numbers[temp] = temp; 20 } 21 } 22 return false; 23 } 24 }
居然能找到错误,开森
/* 一开始交换写错了写成了这:
int temp = numbers[i];
numbers[i] = numbers[numbers[i]];
numbers[numbers[i]] = temp;
于是就错了...
*/
思路二:利用HashMap或者HashTable
不建议
这种方法时间复杂度和空间复杂度都为O(n)。
1 public boolean duplicate(int array[],int length,int [] duplication) { 2 if ( array==null ) return false; 3 4 // 判断数组是否合法(每个数都在0~n-1之间) 5 for ( int i=0; i<length; i++ ) { 6 if ( array[i]<0 || array[i]>length-1 ) { 7 return false; 8 } 9 } 10 11 // key step 12 int[] hash = new int[length]; 13 for( int i=0; i<length; i++ ){ 14 hash[array[i]]++; 15 } 16 for(int i=0; i<length; i++){ 17 if ( hash[i]>1 ) { 18 duplication[0] = i; 19 return true; 20 } 21 } 22 return false; 23 }
另外一个相似的题目
在一个长度为n+1的数组里的所有数字都在1~n范围内,所以数字中至少有一个数字是重复的。请找出数组中任意一个重复的数字,但是不能修改数组。例如,如果输入长度为8的数组{2,3,5,4,3,2,6,7},那么对应的输出是重复的数字2或3。(n+1个元素,n种可能的取值)
最优解法:避免使用O(n)的辅助空间。我们把取值空间[1,n]从中间的数字m分为两部分,前面一部分为1~m,后面一部分为m+1~n。如果数组中元素落在前面一部分的元素个数多于m个,那么数组中重复的元素一定落在前半区间;否则,数组中重复的元素一定落在后半区间。然后,我们可以继续将包含重复元素的区间一分为二,直到找到一个重复的元素。
标签:统计 inpu poi 输入 input ret == OLE other
原文地址:https://www.cnblogs.com/shareidea94/p/11237176.html