在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
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
package array;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class FindOneOfDuplicateNumbers {
/*=====================================================================================*/
/*自想1:排序再遍历一遍找到第一个重复的数字
* 时间复杂度O(nlogn),空间复杂度O(1),修改了原数组
* 如果要求不修改原数组,拷贝一份之后再排序再遍历,时间复杂度不变,空间复杂度变为O(n)
* */
public static int findDuplicate1(int[] nums) {
if (nums == null || nums.length <= 1) {
throw new RuntimeException("invalid input!");
}
Arrays.sort(nums);
for (int i = 0; i < nums.length - 1; i++) {
if (nums[i] == nums[i + 1])
return nums[i];
}
throw new RuntimeException("cannot find duplicate number");
}
// 自想1改成要求的格式
public boolean duplicate1(int numbers[],int length,int [] duplication) {
if (numbers == null || numbers.length <= 1) {
return false;
}
Arrays.sort(numbers);
for (int i = 0; i <= numbers.length - 2; i ++) {
if (numbers[i] == numbers[i + 1]) {
duplication[0] = numbers[i];
return true;
}
}
return false;
}
/*=====================================================================================*/
/*自想2:
* 利用HashSet,如果有已经存在的则直接返回
* 时间复杂度O(n),空间复杂度O(n)
* */
public static int findDuplicate2(int[] nums) {
if (nums == null || nums.length <= 1) {
throw new RuntimeException("invalid input!");
}
Set<Integer> set = new HashSet<>();
for (int num : nums) {
if (set.contains(num)) {
return num;
} else {
set.add(num);
}
}
throw new RuntimeException("cannot find duplicate number");
}
// 自想2改成要求的格式
public boolean duplicate2(int numbers[],int length,int [] duplication) {
if (numbers == null || numbers.length <= 1) {
return false;
}
Set<Integer> set = new HashSet<>();
for (int num : numbers) {
if (set.contains(num)) {
duplication[0] = num;
return true;
}
set.add(num);
}
return false;
}
/*=====================================================================================*/
/*《剑指offer第2版》P39:
* index[0,n-1] value[0,n-1]
* 寻求index-value的对应关系,期待index==value
* 从i=0开始看nums[i]是否==i,
* 如果nums[i]==v(v!=i),则看nums[v],如果nums[v]==v则找到两个==v的数,则将v返回
* 如果nums[v]!=v,则将nums[i]与nums[v]位置交换,期望把每个数都放在index==value的正确位置上
* 时间复杂度O(n),空间复杂度O(1)
* */
public static int findDuplicate3(int[] nums) {
int i = 0;
while (i < nums.length) {
int v = nums[i];
if (v == i) {
i ++;
continue;
}
if (nums[v] == v) {
return v;
}
swap(nums, i, v);
}
throw new RuntimeException("cannot find duplicate number");
}
public static void swap(int[] nums, int i, int j) {
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
// 改成要求的格式
public boolean duplicate3(int numbers[],int length,int [] duplication) {
if (numbers == null || numbers.length <= 1) {
return false;
}
for (int i = 0; i < numbers.length; i ++) {
while (numbers[i] != i) {
int v = numbers[i];
if (numbers[v] == v) {
duplication[0] = v;
return true;
}
swap(numbers, i, v);
}
}
return false;
}
/*=====================================================================================*/
public static void main(String[] args) {
int[] nums1 = new int[]{3, 1, 3, 4, 1};
System.out.println(findDuplicate1(nums1));
System.out.println(findDuplicate2(nums1));
System.out.println(findDuplicate3(nums1));
System.out.println("=========================================================");
int[] nums2 = new int[]{1, 2, 3, 2, 3, 5};
System.out.println(findDuplicate1(nums2));
System.out.println(findDuplicate2(nums2));
System.out.println(findDuplicate3(nums2));
}
}