Find the Duplicate Number 解答

Question

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.

Solution 1 -- Binary Search

题目要求时间复杂度小于O(n2),于是我们就想有没有O(n log n)或者O(n)的做法。一些排序算法是O(n log n),但是题目要求不能更改原序列且空间复杂度为O(1)。

Binary search的复杂度是O(log n),前提是排好序的数组。所以肯定不能用输入数组来进行二分查找。

这一题提供了一个思路是对可行解序列/集合进行二分查找。

由于题目中有明确的各个元素的取值范围,我们可以判断出解一定在[1, n]这个区间内。start = 1, end = n。对于每个mid值,我们计算等于mid的count和小于等于mid的count。

注意:

smallerCount 是和mid值比较。比如mid = 5,那么如果smallerCount <= 5,说明解一定不在[1,5]这个区间内。

 1 public class Solution {
 2     public int findDuplicate(int[] nums) {
 3         int start = 1, end = nums.length - 1, mid;
 4         while (start + 1 < end) {
 5             mid = (end - start) / 2 + start;
 6             int smallerMid = 0;
 7             for (int i : nums) {
 8                 if (i <= mid) {
 9                     smallerMid++;
10                 }
11             }
12             // Compare with mid
13             if (smallerMid <= mid) {
14                 start = mid;
15             } else{
16                 end = mid;
17             }
18         }
19         int countStart = 0;
20         for (int i : nums) {
21             if (i == start) {
22                 countStart++;
23             }
24         }
25         if (countStart > 1) {
26             return start;
27         }
28         return end;
29     }
30 }

Solution 2

参考Discuss,发现有O(n)的解法

参考Linked List II,我们将输入的array也可看作是list,每个数组元素代表这个node的next

 1 public class Solution {
 2     public int findDuplicate(int[] nums) {
 3         if (nums == null || nums.length < 2) {
 4             return 0;
 5         }
 6         int slow = nums[0];
 7         int fast = nums[slow];
 8         while (fast != slow) {
 9             slow = nums[slow];
10             fast = nums[nums[fast]];
11         }
12         fast = 0;
13         while (fast != slow) {
14             slow = nums[slow];
15             fast = nums[fast];
16         }
17         return slow;
18     }
19 }
原文地址:https://www.cnblogs.com/ireneyanglan/p/4946660.html