这道题leetcode和剑指Offer题目略有不同。leetcode说数组中的重复数可能不止一个,但是结果要求返回一个就行;剑指Offer上说只有一个重复的数,但是重复的次数不一定。两个题目的共性就是只需要返回一个重复的数即可。
leetcode 题目:
给定一个包含 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) 。
- 数组中只有一个重复的数字,但它可能不止重复出现一次。
思路:
由于不能使用额外的空间,不能使用记录或统计出现的数,又不能破坏数组结构,不能通过排序来判断相邻数是否相等。
1.暴力法,两层循环,时间复杂度O(n2)太高。
2.用集合保存遍历值,时间复杂度n,但有额外空间开销。
3.归并排序,时间复杂度nlogn,空间复杂度 O(1),但破坏数组结果。
4.二分法,因为数出现在[1,n]。所以统计[1-n/2]的数,如果出现小于等于n/2的数个数超过n/2,[1-n/2]数中有重复的数,继续通过二分减少搜索范围,这里的时间复杂度为nlogn。
代码:
class Solution:
def findDuplicate(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
low,high = 1,len(nums)
while low < high:
count = 0
mid = (low + high)//2
for item in nums:
if item <= mid:
count += 1
if count > mid:
high = mid
else:
low = mid + 1
return low