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.
Example 1:
Input:[1,3,4,2,2]
Output: 2Example 2:
Input: [3,1,3,4,2] Output: 3
Note:
- You must not modify the array (assume the array is read only).
- You must use only constant, O(1) extra space.
- Your runtime complexity should be less than O(n2).
- There is only one duplicate number in the array, but it could be repeated more than once.
题意是在一个数组中找到重复的数字。数组包含N + 1个数字,数字在1 <= x <= n之间。两种解法。
1. 二分法。注意数组是无序的。当得到数组长度len和数组长度的一半mid之后,用count记录有多少个数小于等于中间数mid。举个例子,如果数组长度是10,mid则是5,这里mid指的是数组长度的一半。如果小于mid的个数大于数组的一半,说明重复的数字一定是小于mid的;反之如果大于mid的个数过半,重复的数字一定是大于mid的。用二分法逐渐逼近这个值,注意return的是start。
时间O(nlogn)
空间O(1)
Java实现
1 class Solution { 2 public int findDuplicate(int[] nums) { 3 int min = 0; 4 int max = nums.length - 1; 5 while (min <= max) { 6 int mid = min + (max - min) / 2; 7 int count = 0; 8 for (int i = 0; i < nums.length; i++) { 9 if (nums[i] <= mid) { 10 count++; 11 } 12 } 13 if (count > mid) { 14 max = mid - 1; 15 } else { 16 min = mid + 1; 17 } 18 } 19 return min; 20 } 21 }
JavaScript实现
1 /** 2 * @param {number[]} nums 3 * @return {number} 4 */ 5 var findDuplicate = function(nums) { 6 let start = 1; 7 let end = nums.length - 1; 8 while (start < end) { 9 let middle = Math.floor((start + end) / 2); 10 let count = 0; 11 // 计算总数组中有多少个数小于等于中间数 12 for (let i = 0; i < nums.length; i++) { 13 if (nums[i] <= middle) { 14 count++; 15 } 16 } 17 18 if (count <= middle) { 19 start = middle + 1; 20 } else { 21 end = middle; 22 } 23 } 24 return start; 25 };
2. 快慢指针。因为数组一定是有重复数字出现的所以可以用快慢指针的思路做。当快慢指针相遇之后,再走第二遍,找到重复的数字。
时间O(n)
空间O(1)
Java实现
1 class Solution { 2 public int findDuplicate(int[] nums) { 3 int len = nums.length; 4 if (len > 1) { 5 int slow = nums[0]; 6 int fast = nums[nums[0]]; 7 while (slow != fast) { 8 slow = nums[slow]; 9 fast = nums[nums[fast]]; 10 } 11 slow = 0; 12 while (slow != fast) { 13 slow = nums[slow]; 14 fast = nums[fast]; 15 } 16 return slow; 17 } 18 return -1; 19 } 20 }
JavaScript实现
1 /** 2 * @param {number[]} nums 3 * @return {number} 4 */ 5 var findDuplicate = function(nums) { 6 const len = nums.length; 7 if (len > 0) { 8 let slow = nums[0]; 9 let fast = nums[nums[0]]; 10 while (slow !== fast) { 11 slow = nums[slow]; 12 fast = nums[nums[fast]]; 13 } 14 slow = 0; 15 while (slow !== fast) { 16 slow = nums[slow]; 17 fast = nums[fast]; 18 } 19 return slow; 20 } 21 return -1; 22 };