import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
public class findDuplicateNumber {
//方法一:双指针暴力组合 时间超限
public static int findDuplicate(int[] nums) {
int n = nums.length;
//定义双指针
int first = 0;
int next = 0;
for (int i = 0; i <n-1; i++) {
for (int j = i+1; j < n; j++) {
if(nums[i]==nums[j]){
return nums[i];
}
}
}
return -1;
}
//方法二:使用hashmap保存每个数组出现的次数
public static int findDuplicate2(int[] nums) {
HashMap<Integer,Integer> countMap = new HashMap<>();
//遍历所有元素,统计count值
for (Integer num:nums) {
if(countMap.containsKey(num)){
return num;//如果出现 那么就是重复数
}else{
countMap.put(num,1);
}
}
return -1;
}
//方法三:使用hashset保存数据,判断是否出现过
public static int findDuplicate3(int[] nums) {
HashSet<Integer> hashSet = new HashSet<>();
//遍历所有元素,统计count值
for (Integer num:nums) {
if(hashSet.contains(num)){
return num;//如果出现 那么就是重复数
}else{
hashSet.add(num);
}
}
return -1;
}
//方法四:先排序 然后比较相邻元素
public static int findDuplicate4(int[] nums) {
Arrays.sort(nums);
for (int i = 0; i <nums.length-1; i++) {
if(nums[i]==nums[i+1]){
return nums[i];
}
}
return -1;
}
// 方法五:二分查找,查找1~N的自然数序列,寻找target
public static int findDuplicate5(int[] nums) {
int left= 1;
int right = nums.length-1;
while (left<=right){
//计算中间值
int mid =(left+right)/2;
//对当前的mid计算count值
int count = 0;
for (int i = 0; i <nums.length ; i++) {
if(nums[i]<=mid){
count++;
}
}
//判断count和mid的大小关系
if(count<=mid){
left = mid+1;//count小于等于mid自身,说明mid比target小,左指针右移
}else{
right = mid;
}
//当左右指针重合时找到target
if(left==right){
return left;
}
}
return -1;
}
//方法六:快慢指针法
public static int findDuplicate6(int[] nums) {
// 定义快慢指针
int fast = 0, slow = 0;
// 1. 寻找环内的相遇点
do {
// 快指针一次走两步,慢指针一次走一步
slow = nums[slow];
fast = nums[nums[fast]];
}while (fast != slow);
// 循环结束,slow和fast相等,都是相遇点
// 2. 寻找环的入口点
// 另外定义两个指针,固定间距
int before = 0, after = slow;
while (before != after){
before = nums[before];
after = nums[after];
}
// 循环结束,相遇点就是环的入口点,也就是重复元素
return before;
}
public static void main(String[] args) {
// int[] nums = {1,1};
int[] nums = { 1,3,4,2,2};
int num = findDuplicate6(nums);
System.out.println(num);
}
}