题目描述如下:
给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。
示例 1:
输入: [1,3,4,2,2]
输出: 2
示例 2:
输入: [3,1,3,4,2]
输出: 3
说明:
不能更改原数组(假设数组是只读的)。
只能使用额外的 O(1) 的空间。
时间复杂度小于 O(n2) 。
数组中只有一个重复的数字,但它可能不止重复出现一次。
这道题我提供四种方法供大家参考。
第一种方法:暴力法
这种方法会超时,仅供大家理解使用。
暴力法的思路很简单,从列表的第一个元素开始遍历,然后从后面的列表中寻找是否有和当前元素相同的元素,没有则继续遍历,有则返回。
Python3代码如下:
class Solution:
def findDuplicate(self, nums):
if len(nums)==0:
return -1
elif len(nums)==2:
return nums[0]
for i in range(0,len(nums)-1):
if nums[i] in nums[i+1:len(nums)]:
return nums[i]
第二种方法是集合法,思路就是将列表nums先set一下(nums本身不变),去除重复元素,然后循环遍历set后的列表,从nums中去除set后的列表中的元素,剩下的元素就是重复的元素,然后返回nums列表的第一个元素即可。这种方法虽然可以通过,但是效率非常低,跑完所有用例需要大约2500毫秒的时间。
Python3代码如下:
class Solution:
def findDuplicate(self, nums):
if len(nums)==0:
return -1
elif len(nums)==2:
return nums[0]
for x in list(set(nums)):
nums.remove(x)
return nums[0]
第三种方法是排序法。这种方法的效率远高于上一种方法。
这种方法的思路也很简单,就是先将nums排序,然后从nums列表的第二个元素开始,逐个与前面的元素比较,如果相等则返回该元素。
Python3代码如下:
class Solution:
def findDuplicate(self, nums):
#排序
if len(nums)==0:
return -1
nums.sort();
for i in range(1,len(nums)):
if nums[i]==nums[i-1]:
return nums[i]
跑完所有用例大约需要120毫秒的时间。
最后一种是官方给出的题解,叫循环检测,说实话,这种方法我没看懂,下面贴出官方的解释,希望看懂的朋友能分享一下自己的见解。
Python3代码如下:
class Solution:
def findDuplicate(self, nums):
# Find the intersection point of the two runners.
tortoise = nums[0]
hare = nums[0]
while True:
tortoise = nums[tortoise]
hare = nums[nums[hare]]
if tortoise == hare:
break
# Find the "entrance" to the cycle.
ptr1 = nums[0]
ptr2 = tortoise
while ptr1 != ptr2:
ptr1 = nums[ptr1]
ptr2 = nums[ptr2]
return ptr1
这种方法的效率更高,只需要大约80毫秒就能跑完所有用例。