Find the Duplicate Number

LeetCode Q 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:
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(n^2).
There is only one duplicate number in the array, but it could be repeated more than once.

Solution

Method 1:

We traverse the array, we regard each number in the array as the position, then we mark the number in that position to be negative. Then if the number in that position has already been nagetive, that means we have already visited that position. Then we find the duplicates.

For example,
array: [1, 3, 4, 2, 2]

  • visit 1st number (i.e. 1), change the number in position 1 to be netaetive, then the array becomes [-1, 3, 4, 2, 2]
  • visit 2nd number (i.e. 3), change the number in position 3 to be netaetive, then the array becomes [-1, 3, -4, 2, 2]
  • visit 3rd number (i.e. 4), change the number in position 4 to be netaetive, then the array becomes [-1, 3, -4, -2, 2]
  • visit 4th number (i.e. 2), change the number in position 2 to be netaetive, then the array becomes [-1, -3, -4, -2, 2]
  • visit 5th number (i.e. 2), we find the number in position 2 is negative, then 2 is the duplicates we want to find.

Code:

public int findDuplicate(int[] nums) {
	for (int i = 0; i < nums.length; i++) {
		if (nums[Math.abs(nums[i]) - 1] < 0)
			return Math.abs(nums[i]);
		else
		nums[Math.abs(nums[i]) - 1] \*= -1;
	}
    
	for (int num: nums)
		num = Math.abs(num);

	return -1;
}

Method 2:

This solution is similar to find the solution of the node where the cycle begins. This question can be found in Linked List Cycle II

Code:

public int findDuplicate(int[] nums) {
    int slow = nums[0], fast = nums[0];
	do {
		slow = nums[slow];
		fast = nums[nums[fast]];
	} while (slow != fast);

	int pointer1 = nums[0], pointer2 = slow;
	while (pointer1 != pointer2) {
		pointer1 = nums[pointer1];
		pointer2 = nums[pointer2];
	}

	return pointer1;
}

At first the search space is numbers between 1 to n. Each time I select a number mid (which is the one in the middle) and count all the numbers equal to or less than mid. Then if the count is more than mid, the search space will be [1 mid] otherwise [mid+1 n]. I do this until search space is only one number.

Code:

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

   Reprint policy


《Find the Duplicate Number》 by Tong Shi is licensed under a Creative Commons Attribution 4.0 International License
  TOC