Input:
{2, 3, 1, 0, 2, 5}
Output:
2
题目解析
对于这种数组元素在 [0, n-1] 范围内的问题,可以将值为 i 的元素调整到第 i 个位置上进行求解。本题要求找出重复的数字,因此在调整过程中,如果第 i 位置上已经有一个值为 i 的元素,就可以知道 i 值重复。
解题代码
class Solution:
def duplicate(self, numbers, duplication):
if numbers == None or len(numbers)<=1:
return False
for i in range(len(numbers)):
if numbers[i]<0 or numbers[i]>len(numbers)-1:
return False
for i in range(len(numbers)):
while(numbers[i] !=i):
if numbers[i] == numbers[numbers[i]]:
duplication[0] = numbers[i]
return True
else:
temp = numbers[i]
numbers[i] = numbers[temp]
numbers[temp] = temp
return False
题目二 不修改数组找出重复的数字
描述
在一个长度为n+1的数组里的所有数字都在1~n的范围内,所以数组中至少有一个数字是重复的。请找出数组中任意一个重复的数字, 但不能修改输入的数组,例如输入长度为8的数组[2,3,5,4,3,2,6,7],那么对应的输出是重复的数字为2或3。
题目解析
解题思路:找到规律“在1-n的范围内只有n个数字,如果超过n个数字,则一定包含重复的数字”
基于此思想,将数组长度n的1-n的数字分为m两部分,前一半为1-m,后一半为m+1~n.如果1-m的数字范围的数字,在数组中出现的个数大于m,则在这一半有重复数字,则在此范围内进行查找,相反则在另外一半查找。
题目理解
此题使用的是二分法的变体,可以理解为一种夹逼思想。先对数字范围进行分组,然后在两个分组中再进行查找。注意这里分组的不是要查找的数组,而是数组长度的范围。通过不断的缩小数字范围得到结果,而数组只是用来统计数字出现的次数。
代码实现
class Solution:
def duplicate(self, numbers):
if not numbers or len(numbers)<0:
return -1
start = 1
end = len(numbers)-1
while start<=end: #注意这是左右闭合的写法
middle = (end - start)//2 + start
count = self.countRange(numbers, len(numbers), start, middle)
if end == start:
if count >1:
return start
else:
break
if count > middle - start +1: #如果数字i-m范围出现次数大于m-i+1,则此范围数字有重复
end = middle
else:
start = middle +1
return -1
def countRange(self, numbers, length, start, end):
if not numbers:
return 0
count = 0
for i in range(lenght):
if numbers[i]>= start or numbers[i] <= end:
count+=1
return count