287. Find the Duplicate Number

Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), prove that at least one duplicate number must exist. Assume that there is only one duplicate number, find the duplicate one.

Note:

  1. You must not modify the array (assume the array is read only).
  2. You must use only constant, O(1) extra space.
  3. Your runtime complexity should be less than O(n2).
  4. There is only one duplicate number in the array, but it could be repeated more than once.

加入忽略题目对时间复杂度(less than O(N^2))和空间复杂度(O(1))的要求,可以想到有以下几种方法:

(1)直接搜索法

时间复杂度O(N^2),空间复杂度O(1).

针对每个元素,向后寻找是否存在其重复元素。

(2)哈希表法

时间复杂度O(N),空间复杂度O(N).

用一个集合/map记录已经遍历过的数,如果已经有了说明是重复数字。(集合中元素不可重复,map中key不可重复)

public int findDuplicate(int[] nums){
		Map<Integer,Integer> myMap = new HashMap<Integer,Integer>();
		//Set<Integer> mySet = new HashSet<Integer>();
		for(int num:nums){
			if(myMap.containsKey(num)) return num;
			myMap.put(num, 1);
			/*
			 * if(mySet.contains(num)) return num;
			 * mySet.add(num);
			 */
		}		
		return 0;
	}

(3)排序法

时间复杂度O(N*logN),空间复杂度O(1)/O(N). (如果不复制数组,则空间复杂度为O(1),但是排序时会改变原数组;复制数组则空间复杂度为O(N)).

public int findDuplicateBySort(int[] nums){
		Arrays.sort(nums);
		for(int i=1;i<nums.length;i++){
			if(nums[i] == nums[i-1]) return nums[i];
		}
		return 0;
	}
public int findDuplicateBySortAndCopy(int[] nums){
        int[] newArr = Arrays.copyOf(nums, nums.length);
        Arrays.sort(newArr);
        for(int i=1;i<nums.length;i++){
            if(newArr[i] == newArr[i-1]) return newArr[i];
        }
        return 0;
    }

然后看了网上的一些参考答案,寻找到一些符合题目要求的算法:

(1)二分法

由于这n+1个数字介于1~n之间,首先用二分法选择n/2作为比较对象,当整个数组中小于等于n/2的数字超过n/2,说明1~n/2之间肯定有重复数字,否则n/2~n之间肯定有重复数字,下次在有重复数字的区间内再次使用二分法。

public class Solution {
    public int findDuplicate(int[] nums) {
        int min = 0, max = nums.length-1;
        while(min<=max){
            int mid = (max-min)/2+min;
            int count = 0;
            for(int i=0;i<nums.length;i++)
                if(nums[i]<=mid) count++;
            if(count<=mid)
                min = mid+1;//后半部分有重复
            else max = mid-1; //前半部分有重复
        }
        
        return min;
    }
}
(2)寻找环路法
元素index和元素本身之间存在一个映射关系,从下标0开始,可以产生一个类似链表的序列,如果存在重复元素,则会出现环路,我们就是要寻找环路的起点。

https://en.wikipedia.org/wiki/Cycle_detection#Tortoise_and_hare

有时间多看看==






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值