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.
给一个数组,其中一定有且只有一个数字是重复的,找出那个数字;
O(n2)的算法就不说了
法一 O(n)空间 O(n)时间,开一个set直接记录
class Solution { public int findDuplicate(int[] nums) { Set<Integer> set = new HashSet<>(); for (int i = 0; i < nums.length; i++) { if (set.contains(nums[i])) return nums[i]; else set.add(nums[i]); } return -1; } }
法二 先排序再找 时间O(nlogn) 空间O(1)
class Solution { public int findDuplicate(int[] nums) { Arrays.sort(nums); for (int i = 1; i < nums.length; i++) { if (nums[i] == nums[i - 1]) return nums[i]; } return -1; } }
法三,把这个数组看成列表
因为里面的元素是小于n的,所以可以这么做
比方说数组是 1 3 2 3 4 那么
下标就是 0 1 2 3 4
那么 让其元素连接下标 使之构成链表,那么其中一定存在环,就可以用142. Linked List Cycle II那个算法了()
class Solution { public int findDuplicate(int[] nums) { int slow = nums[0]; int fast = nums[0]; while (slow != fast) { slow = nums[slow]; fast = nums[nums[fast]]; } slow = 0; while (slow != fast) { slow = nums[slow]; fast = nums[fast]; } return slow; } }
补充:这题还有一个O(nlogn)的解法,就是利用二分法,我不推荐用这个解法,因为大多数人用二分法时都会因为边界问题而出错
这个算法里要反复使用二分,说来惭愧,我二分也常常出错,所以就不丢人,有兴趣的同学可以去查一下