一、题目
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
二、思路
- 调用API对数组排序,然后遍历数组,当相邻两项相等时,返回nums[i]即为所求。
- 哈希表1:用哈希表转存,遍历数组,存入哈希表先先判断元素是否已存在。若已存在,则返回
- 遍历数组,将元素存入哈希表,若存入失败,返回的元素即为所求;
- 下标法:由于本题规定nums的元素范围均小于n,则利用元素与下标的关系,通过不停交换元素,使得元素和它所对应的下标相等。num[num[i]]=nums[i]。若存在相同元素,返回
nums[i]即为所求;
- 解法1:先排序,后比较
空间复杂度为O(logn),时间复杂度为O(logn)
public int findRepeatNumber(int[] nums) {
// 边界判断
if(nums==null || nums.length==0){
return -1;
}
Arrays.sort(nums);
for(int i = 0 ; i < nums.length-1 ;i++){
if(nums[i]==nums[i+1]) {
return nums[i];
}
}
return -1;
}
修改了原数据,若要求返回下标,则不妥。
- 哈希表1
空间复杂度为O(n),时间复杂度为O(n)
public int findRepeatNumber(int[] nums) {
// 边界判断
if(nums==null || nums.length==0){
return -1;
}
Set<Integer> set = new HashSet<>();
for(int num:nums){
if(set.contains(num)) {
return num;
}
set.add(num);
}
return -1;
}
- 哈希表2
public int findRepeatNumber(int[] nums) {
// 边界判断
if(nums==null || nums.length==0){
return -1;
}
Set<Integer> set = new HashSet<>();
for(int num:nums){
if(!set.add(num)){
return num;
}
}
return -1;
}
- 下标法(最优解):利用元素与下标的关系。
- 时间复杂度O(n),空间复杂度O(1)
public int findRepeatNumber(int[] nums) {
// 边界判断
if(nums==null || nums.length==0){
return -1;
}
for(int i = 0 ; i < nums.length;i++){
while(i!=nums[i]){
//重复返回
if(nums[i]==nums[nums[i]]){
return nums[i];
}
//交换
int temp = nums[nums[i]];
nums[nums[i]] = nums[i];
nums[i] = temp;
}
}
return -1;
}
- 最后提交
-
解答成功:
执行耗时:0 ms,击败了100.00% 的Java用户
内存消耗:48.5 MB,击败了95.26% 的Java用户
-