题目:不修改数组找出重复数字
题目:不修改数组找出重复数字,在一个长度为n+1的数组里的所有数字都在1~n的范围内,所以数组至少有一个数字是重复的。请找出数组中任意一
个重复的数字,但不能修改输入的数组,例:长度为8的数组{2,3,5,4,3,2,6,7},那么对应的输出应该是重复的数字2或者3.
第一时间想到借助辅助空间,创建同等长度的数组,已知长度为n,数字范围1~n+1,设定原数组nums[],新数组ans[],即将原数组的值放入对应新数组下标的位置上,例子:原数组第一个值2,赋值新数组ans[2]=2,上代码。
public static Integer getRepeatingNum(int nums[]){
//判空,临界情况
if(nums==null || nums.length==0){
return null;
}
//int空数组初始化默认值为0,Integer为null;
Integer ans[] = new Integer[nums.length];
for(int i=0;i<nums.length;i++){
int temp = nums[i];
//初始值为null,非初始值则代表已存放过,即重复数字
if(ans[temp]!=null){
return ans[temp];
}
//将对应的数值防止对应下标位,6->ans[6]
ans[temp] = nums[i];
}
return null;
}
官方解法:核心思想是二分查找,1~n的数组,设定中间数字m,分为1~m,m+1~n两部分,如果1~m的数字数量超过m,那么这一半的区间一定包含重复数字,否则另一半m+1~n包含重复数字,然后继续对包含重复数字的区间一分为二,直至找到重复数字为准。
例:{2,3,5,4,3,2,6,7}
长度为8,所有数字均在1~7的范围,中间数字是4,统计1,2,3,4(1~m)这四个数字在数组出现的次数,它们出现了5次,因此这四个数字中必定含有重复数字。上代码。
//统计数组数字出现的次数
public static int countRange(int temps[],int length,int start,int end){
if(temps == null){
return 0;
}
int count = 0;
for (int i=0;i<length;i++){
//统计start至end这个范围内,数组中数字出现的个数,例:理论上1~4,应该是4,如大于4则代表有重复数字
if(temps[i]>=start && temps[i]<=end){
++count;
}
}
return count;
}
public static Integer getRepeatingNumNew(int nums[],int length) {
//判空,临界情况
if (nums == null || nums.length == 0) {
return null;
}
int start =1;
int end = nums.length-1;
while(end>=start){
int middle = (end-start)/2+start;
int count = countRange(nums,length,start,middle);
if(end == start){
if (count>1){
return start;
}
break;
}
if(count>(middle-start+1)){
end = middle;
}else {
start = middle + 1;
}
}
return -1;
}
总结:
- 面试官的要求一定要听清楚
- 编写代码,注意方法变量命令规范(英文语义,大小写),判空,临界条件,不能只考虑正常情况
- 先实现出自己能写出来的,后面再考虑其他解法