JZ50 数组中重复的数字
my version
出错记录:
- 没有考虑输入为空的情况[]
时间复杂度O(n) 空间复杂度O(n)
class Solution:
def duplicate(self , numbers ):
if numbers:
n = [0] * len(numbers)
for i in numbers:
if i < 0 or i >= len(numbers):
return -1
elif n[i] != 0:
return i
else:
n[i]+=1
else:
return -1
book method1
考虑空间复杂度为O(1)的情况 时间复杂度仍为O(n)
数组中数字范围0~n-1,若无重复数字则排序后数字i出现位置的下标也为i
class Solution:
def duplicate(self , numbers ):
if numbers:
for i in range(len(numbers)):
if numbers[i] >0 and numbers[i] <len(numbers):
while numbers[i] != i:
if numbers[numbers[i]] != numbers[i]:
tmp = numbers[numbers[i]]
numbers[numbers[i]] = numbers[i]
numbers[i] = tmp
else:
return numbers[i]
return -1
book method2
当题目改为长度为n+1,数字范围在1~n范围内时才适用如下算法,
否则若题目为长度为n,数字范围在0~n-1出现例如[2,1,3,1,4] 则n=5,划分为0~2和3~4其中<=2且>=0的有3个和位数3相同,无法找到,
因此,只有在题目为长度为n+1,数字范围在1~n范围内时,n=4,化分为1~2和3~4,其中<=2且>=1的有3个>位数2因此重复的数出现在此区域内,再继续二分查找。
数字范围为1~n共n个,可长度为n+1说明一定有重复的。
不修改数组本身 考虑类似二分查找的方法,统计相应范围内数字出现的次数 时间复杂度O(nlogn) 空间复杂度O(1)
出错记录:
- 二分查找时 mid = (end - start) / 2 + start, 否则查找后半段的下标会出错
class Solution:
def countRange(self, start, end, numbers):
count = 0
for i in range(len(numbers)):
if numbers[i] <0 or numbers[i] >=len(numbers):
return -1
elif numbers[i] >= start and numbers[i] <= end:
count += 1
return count
def duplicate(self , numbers ):
if numbers:
start = 1
end = len(numbers)-1
while (start <= end):
mid = (end - start) // 2 + start
count = self.countRange(start, mid, numbers)
if start == end:
if count >1 :
return start
else:
break
if count > (mid-start)+1:
end = mid
else:
start = mid + 1
return -1