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 one–Binary search
以下步骤循环进行直到指针
low
l
o
w
比
high
h
i
g
h
要大:
1.找到
low
l
o
w
和
high
h
i
g
h
的中间点
mid=low+(high−low)/2
m
i
d
=
l
o
w
+
(
h
i
g
h
−
l
o
w
)
/
2
,将待搜索待搜索区域划为两段
[low,mid],[mid,high]
[
l
o
w
,
m
i
d
]
,
[
m
i
d
,
h
i
g
h
]
。对数值落在其中一个区域的元素进行计数,如
[low,mid]
[
l
o
w
,
m
i
d
]
,若落在该区域的元素数量大于该区域的容量
mid−low
m
i
d
−
l
o
w
则说明重复元素落在该区域,否则落在另一区域。
2.依照新的待搜索区域更新
low
l
o
w
或
high
h
i
g
h
,以及
mid
m
i
d
。
代码如下:
class Solution:
def findDuplicate(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
low,high = 0,len(nums)-1
while low<=high:
count = 0
mid = low+(high-low)//2
for n in nums:
#这里实际是计的落在[0,mid]区域内元素的数量
#即每次都搜索整个数组,将整个数组划分为[0,mid],[mid,high]
#low只是作为寻找mid的辅助指针
if n<=mid:
count += 1
if count<=mid:
low = mid+1
else:
high = mid-1
return low
Solution Two–龟兔赛跑
先放代码
class Solution:
def findDuplicate(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
slow,fast = nums[0],nums[nums[0]]
while fast!=slow:
slow = nums[slow]
fast = nums[nums[fast]]
fast = 0
while fast!=slow:
fast = nums[fast]
slow = nums[slow]
return fast
这个算法的思想借鉴于leetcode的题目:Linked List Cycle II。
将数组看成一个链表,数组元素的序号视为指向链表元素的指针,数组元素的值视为链表元素(值相同则视为同一链表元素)。由于数组中存在重复元素,则数组对应的链表一定存在环(有多个指针指向同一元素,该元素也是环的起点)。
第一个while循环用来寻找环是否存在,本题已经能确定一定有环,则用来寻找cross point X。
第二个while循环中,将其中一个指针指回head,该指针走过距离H刚好等于另一指针从X走外圈到E的距离,就可以找到E(即重复元素)。
证明:
第一个while中,
fast指针走过的距离是:H+L(环的长度)+D
slow指针走过的距离:H+D
又有每次slow走一步,fast都会走两步:2H+2D = H+D+L, 即 H+D = L
那么fast指向head之后一次也只走一步了,它走过H距离的同时, slow刚好走过L-D, 二者在E点汇合。
Consider the following linked list, where E is the cylce entry and X, the crossing point of fast and slow.
H: distance from head to cycle entry E
D: distance from E to X
L: cycle length
__
/ \
head_____H______E \
\ /
X_____/