题目
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。 也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
分析
(1)直接想到的可以使用hashmap,遍历一次,时间复杂度是O(n),空间复杂度是O(n);
(2)可以使用排序,排序后遍历,比较前后两个数是否相同,时间复杂度是O(nlogn);
(3)使用一个Boolean数组存储,遍历原整数数组,将原数组对应元素的值隐射成Boolean数组的下标,并存储成true。
为啥要用这个数组呢?
1.boolean不是占1位,计算机处理处理数据的最小单元是1字节,一般1位的话,其余7位会被0补齐。
2.在java虚拟机规范中,JVM没有用于操作boolean的字节码指令,在编译后用int的数据类型代替boolean,此时boolean占4字节。
3.boolean[]数组编译后会被byte[]数组代替,此时的boolean占1字节。
总结:boolean单独存在占4字节,在boolean[]中占1字节!
这是网友的解答,所以用Boolean可以减少内存的使用。
代码
我使用第三种方法结题,代码如下:
public 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 (numbers== null || length == 0) {
return false;
}
boolean [] tempBooleans = new boolean[length];
for(int i =0;i< length;i++){
// 将numbers数组的元素作为数组的下标,出现过的元素对应的下标存储true
if (tempBooleans[numbers[i]]== true) {
duplication[0] = numbers[i];
return true;
}
tempBooleans[numbers[i]] = true;
}
return false;
}
}