文章目录
二分查找问题
- 二分查找的时间复杂度是O(logn)
6, 287. 寻找重复数
https://leetcode-cn.com/problems/find-the-duplicate-number/
思路1: 遍历时候把数据使用hashmap存储下来
- 时间复杂度:O(n)
- 空间复杂度:O(n)
思路2: 遍历时候把数据使用hashset存储下来
- 时间复杂度:O(n)
- 空间复杂度:O(n)
思路3: 先排好序,然后遍历,如果当前数等于下一个数,则找到重复数字
- 时间复杂度:O(nlogn)
- 空间复杂度:O(1)
思路4: 遍历1-n,然后查找数组中比遍历的当前数字i小的数字有几个,假设个数大于i个,则说明就是重复数字就是i
思路5: 思路4优化:遍历1-n的时候,不使用逐个遍历,而是二分查找。
- 这里终止条件和思路4就不太一样了,需要left=right才能结束
思路6: 双指针法
具体思路参考:
https://leetcode-cn.com/problems/find-the-duplicate-number/solution/kuai-man-zhi-zhen-de-jie-shi-cong-damien_undoxie-d/
package com.shangguigu.dachang.algrithm.A02_binary;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
/**
* @author : 不二
* @date : 2022/4/6-下午10:30
* @desc : https://leetcode-cn.com/problems/find-the-duplicate-number/
**/
public class A25_findDuplicate {
public static void main(String[] args) {
int[] nums = {
1, 3, 4, 2, 2};
// int duplicate = findDuplicate_v1(nums);
// int duplicate = findDuplicate_v2(nums);
int duplicate = findDuplicate_v6(nums);
System.out.println("重复的数字是:" + duplicate);
}
/**
* 第6中方法:使用快慢指针
* 这个思路也太妙了
* 具体可以看:https://leetcode-cn.com/problems/find-the-duplicate-number/solution/kuai-man-zhi-zhen-de-jie-shi-cong-damien_undoxie-d/,
* 这里解释的比较清楚
*/
public static int findDuplicate_v6(int[] nums){
int slow = 0, fast = 0;
while (true) {
slow = nums[slow];
fast = nums[nums[fast]];
// 说明在圈中相遇
if (slow == fast) {
break;
}
}
/*do {
slow = nums[slow];
fast = nums[nums[fast]];
} while (slow != fast);*/
int finder = 0;
slow = slow;
while (true) {
slow = nums[slow];
finder = nums[finder];
if (slow == finder) {
break;
}
}
return finder;
}
/**
* 第5种方法:第4种方法优化:
* 第一次遍历的时候, 不使用普通遍历,而是使用二分查找遍历,提高效率
*
* @param nums
* @return
*/
public static int findDuplicate_v5(int[] nums) {
int left = 1;
int right = nums.length-1;
while (left < right) {
int theValue = (left+right)/2;
int count = 0;
for (int j = 0; j < nums.length; j++) {
if (nums[j] <= theValue) {
count++;
}
}
if (count > theValue) {
// 这里注意不要减去1
right = theValue;
} else {
left