There is only one duplicate number in the array, but it cocould be repeated more than once.
Analysis:
Given an array, the length of the array is n + 1, and the number is between 1 and n. In this way, there must be one number in the array twice. Assume that only one number is repeated to find the number.
Requirement: the array cannot be modified and is read-only. Only constant spaces are allowed. The algorithm complexity is smaller than O (n ^ 2), meaning no violence. Assume that there is only one repeat number, but it can appear many times.
I thought about this question for a long time. View Discuss to understand.
Solution 1:
I used the fresh Cycle detection method. I remember I wrote a question called Linked List Cycle yesterday, which was written by this method.
The idea is to map array elements and subscripts one by one based on the characteristics of array elements. For example, if the array is 13422, 0 corresponds to 1, 1, 3, 2, 4, and so on. In this way, if you think of this ing as a chain, you can follow the subscript, subscript corresponding value, subscript corresponding value corresponding to the underlying value, always traverse, there is a ring in the chain, in the end, it will be in a loop. For example, for the above array, it will eventually fall into a loop where subscript 2 corresponds to value 4, subscript 4 corresponds to value 2, and subscript 2 corresponds to value 4.
It is not enough to find the loop. We also need to find the number into the loop, which is the number of duplicates to find. You can use a new value with a subscript of 0 to map from the beginning. When we encounter a pointer in the previous loop, we find the starting point of the loop.
Code 1:
Class Solution (object): def findDuplicate (self, nums): type nums: List [int]: rtype: int slow, fast = 0, 0 while True: slow = nums [slow] fast = nums [nums [fast] if slow = fast: break # fast and slow must have met at a certain point in the loop, however, the encounter point is not necessarily the element that just enters the loop. # You need to start from 0 and continue searching for find = 0 while find! = Slow: slow = nums [slow] find = nums [find] return find
Solution 2:
Use the binary method.
Code:
class Solution(object): def findDuplicate(self, nums): :type nums: List[int] :rtype: int l, r = 0, len(nums) - 1 while l <= r: mid = l + (r - l) / 2 cnt = 0 for n in nums: if n <= mid: cnt += 1 if cnt > mid: r = mid - 1 else: l = mid + 1 return l