版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/dpengwang/article/details/88075486
找出数组中重复的数,题目中要提取出如下关键信息
- 数组有n+1个数,每个数的范围是1-n(注意有n个数,每个数的范围是1-n的区别)
- 重复的数可能有多个一个,但值都是相同的
方法1 map法 Time O(n) Space O(n)
class Solution1(object):
def findDuplicate(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
dictionary = {}
for num in nums:
if num in dictionary:
return num
else:
dictionary[num] = 1
方法2 排序法 Time O(nlogn) Space O(1)
class Solution2(object):
def findDuplicate(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
nums.sort()
for i in range(len(nums)):
if nums[i] == nums[i+1]:
return nums[i]
方法3 下标法 Time O(n) Space O(1)
因为数组中每个元素的取值范围为1-n,我们可以将访问过的元素,根据他的值,将对应位置的元素变为相反数,如果再次遇到负值,说明该元素重复。这种方法的缺点是原来的数组会被改变。
eg: a[1] = 2 ,我们将a[2]变为 -a[2],a[3] =2是,我们再次访问a[2]发现其为负,说明之前2已经出现过了
class Solution3(object):
def findDuplicate(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
for i in range(len(nums)):
index = abs(nums[i])
if nums[index-1] < 0:
return index
else:
nums[index-1] *=-1
方法4 位操作法 Time O(32n) Space O(1)
我们按位遍历数组中的数和1-n,统计对应的bit上出现的次数,如果重复了某个数,那么该位置上肯定多了个1。
注:这种方法可行是因为题目条件:数组有n+1个数,每个数的范围是1-n,如果条件改为:有n个数,每个数的范围是1-n,那么此方法不适用
class Solution4(object):
def findDuplicate(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
res = 0
for i in range(32):
bit = 1 << i
array_count = 0
origin_count = 0
for i in range(len(nums)):
if nums[i] & bit >0:
array_count +=1
if i>0 and i&bit >0:
origin_count +=1
if array_count > origin_count:
res += bit
return res
方法5 快慢指针法 Time O(n) Space O(1)
数组中元素的值可以看做是其指向下一个元素的下标
eg:
13422可以看做为 1->3->2->4->2(即又指向了2形成了一个换),我们用快慢指针法找出环的入口即可
class Solution5(object):
def findDuplicate(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
slow = nums[0]
fast = nums[slow]
while(slow != fast):
slow = nums[slow]
fast = nums[nums[fast]]
fast = 0
while(fast != slow):
fast = nums[fast]
slow = nums[slow]
return fast
方法6 二分查找法 Time O(nlog(n)) Space O(1)
主要思想如下:
我们根据最大最小值确定一个中位数,然后遍历数组记录小于等于middle的数有多少个。
没有重复的情况下小于等于middle的数应该有middle,如果大于middle,说明重复的数出现在middle左侧,反之在右侧
查找log(n)次,每一次查找中要遍历一次数组O(n)
class Solution6(object):
def findDuplicate(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
low = 1
high = len(nums)-1
while(low < high):
middle = (low + high)//2
count = 0
for num in nums:
if num <= middle:
count +=1
if count <= middle:
low = middle+1
else:
high = middle
return low