LeetCode-442. Find All Duplicates in an Array & 287. Find the Duplicate Number

题目1链接:https://leetcode.com/problems/find-all-duplicates-in-an-array/

题目2链接:https://leetcode.com/problems/find-the-duplicate-number/

这道题目在剑指offer面试题3  P39

先看题目一:

数组大小为n,数组元素A[i]在[1,n]中,里面有重复数字,找出所有重复数字

最朴素的思路一:哈希法

class Solution {
    public List<Integer> findDuplicates(int[] nums) {
        List<Integer> ret=new LinkedList<Integer>();
        HashSet<Integer> set=new HashSet<Integer>();
        for(int i=0;i<nums.length;i++)
        {
            if(set.contains(nums[i]))
                ret.add(nums[i]);
            else
                set.add(nums[i]);
        }
        return ret;
    }
}

时间复杂度为:O(n)

空间复杂度:O(n)

思路二:先用快排,再遍历一遍数组

class Solution {
    public List<Integer> findDuplicates(int[] nums) {
        List<Integer> ret=new LinkedList<Integer>();
        Arrays.sort(nums);
        for(int i=1;i<nums.length;i++)
        {
            if(nums[i]==nums[i-1])
                ret.add(nums[i]);
        }
        return ret;
    }
}

时间复杂度:O(nlogn)

空间复杂度:O(logn)

思路三:用一个长度为(n+1)的计数数组,代码如下:

class Solution {
    public List<Integer> findDuplicates(int[] nums) {
        List<Integer> ret=new LinkedList<Integer>();
        int[] counter=new int[nums.length+1];
        for(int i=0;i<nums.length;i++)
            counter[nums[i]]+=1;
        for(int i=1;i<counter.length;i++)
            if(counter[i]>1)
                ret.add(i);
        return ret;
    }
}

时间复杂度为:O(n)

空间复杂度:O(n)

对于问题二,相较于问题一简单不少,(除了上述解法)但解法多样,非常有趣!

思路一:基于二分法,以1~n为搜索范围,遍历数组搜索小于等于mid的数字的个数count(计数),当count大于mid时,说明重复数字必然在[1,mid]间,缩小范围搜索;否则(count小于等于mid),在(mid,n]之间缩小范围搜索(注意遇见的开闭与二分搜索的写法)。

class Solution {
        public static int findDuplicate(int[] nums) {
        int left=1,right=nums.length-1;
        int mid=0;
        while(left<right)
        {
        	int count=0;
        	mid=left+(right-left)/2;
        	for(int j=0;j<nums.length;j++)
        		if(nums[j]<mid+1)
        			count++;
        	if(count>mid)
        		right=mid;
        	else
        		left=mid+1;
        }
        return left;
    }
}

思路二:基于Floyd龟兔赛跑算法,非常的tricky,具体原理证明参考https://blog.csdn.net/To_be_to_thought/article/details/83958314

class Solution {
    public int findDuplicate(int[] nums) {
        int pFast=0,pSlow=0;
        while(true)
        {
            pSlow=nums[pSlow];
            pFast=nums[nums[pFast]];
            if(pSlow==pFast)
            {
                pFast=0;
                while(pFast!=pSlow)
                {
                    pFast=nums[pFast];
                    pSlow=nums[pSlow];
                }
                return pFast;
            }          
        }
    }
}

猜你喜欢

转载自blog.csdn.net/To_be_to_thought/article/details/84403710