题目描述
//03. 数组中重复的数字 // 找出数组中重复的数字。
// 力扣 // 在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。 // 数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每 // 个数字重复了几次。请找出数组中任意一个重复的数字。
// 牛客 // 在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数 // 字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次 // 。请找出数组中第一个重复的数字。 例如,如果输入长度为7的数组{2,3, // 1,0,2,5,3},那么对应的输出是第一个重复的数字2。 // 返回描述: // 如果数组中有重复的数字,函数返回true,否则返回false。 // 如果数组中有重复的数字,把重复的数字放到参数duplication[0]中。(ps // :duplication已经初始化,可以直接赋值使用。)
排序法
把数组排成升序,再遍历找相邻重复数
// 时间复杂度 O(nlogn):3 ms, 在所有 Java 提交中击败了59.39%的用户
// 空间复杂度 O(1):45.9 MB, 在所有 Java 提交中击败了96.69%的用户
import java.util.Arsrays;
class Solution {
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;
}
}
集合法
很粗暴,直接存hashset,存不进就是遇到重复了
// 时间复杂度 O(n): 5 ms, 在所有 Java 提交中击败了49.49%的用户
// 空间复杂度 O(n):48.1 MB, 在所有 Java 提交中击败了23.18%的用户
import java.util.*;
class Solution {
public int findRepeatNumber(int[] nums) {
Set<Integer> set = new HashSet<>();
int result = -1;
if (nums == null || nums.length <= 0) {
return result;
}
for (int i=0; i <= nums.length-1; i++) {
if (!set.add(nums[i])) { // 如果存不进hashset,说明遇到重复
result = nums[i];
return result; // 返回遍历数
}
}
return result;
}
}
// 牛客
// 牛客题目要求时间复杂度 O(N),空间复杂度 O(1),因此比较严格一点
// 运行时间 14ms
// 占用内存 10048KB
import java.util.HashSet;
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 (length == 0)
return false;
HashSet<Integer> set = new HashSet<>();
for (int i = 0; i < length; i++) {
if (!set.add(numbers[i])) {
duplication[0] = numbers[i];
return true;
}
}
return false;
}
}
原地置换
找重复的数,且数取值在数组长度范围内,大部分数肯定是不重复的,将它们摆放成数字和索引相同的数组,即{0, 2, 3, 1}我们希望摆成{0, 1, 2, 3}。如果数组有两个2,那么原来2的位置有一个2,就会发现重复。
// 时间复杂度 O(n):1 ms, 在所有 Java 提交中击败了90.57%的用户
// 空间复杂度 O(1):45.8 MB, 在所有 Java 提交中击败了98.14%的用户
class Solution {
public int findRepeatNumber(int[] nums) {
if (nums == null || nums.length <= 0) {
return -1;
}
int i = 0; // 初始化索引i
while (i <= nums.length-1) {
// 若遍历数与索引不等
if (nums[i] != i) {
// System.out.println(nums[i]);
// 若遍历数与以遍历数为索引的对应数相等(遇重复)
if (nums[i] == nums[nums[i]]) {
return nums[nums[i]]; // 直接返回结果
}
//交换:遍历数与以遍历数为索引的对应数
swap(nums, i);
} // (交换后)确认遍历数与索引相等之后,再右移索引
else {
i++;
}
}
return -1;
}
// 定义交换方法
private void swap(int[] list, int i) {
int temp = list[list[i]];
list[list[i]] = list[i];
list[i] = temp;
}
}
// 牛客
import java.util.HashSet;
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 (length == 0)
return false;
int i = 0;
while (i < length) {
if (numbers[i] != i){
if (numbers[i] == numbers[numbers[i]]) {
duplication[0] = numbers[numbers[i]];
return true;
}
swap(numbers, i);
}
else
i++;
}
return false;
}
// 使得numbers[i]和numbers[numbers[i]]交换
private void swap(int[] numbers, int i) {
int temp = numbers[numbers[i]];
numbers[numbers[i]] = numbers[i];
numbers[i] = temp;
}
}