题目一:在一个长度为n的数组里的所有数字都在0~n-1的范围内。数组中某些数字是重复的,但是不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。例如,如果输入长度为7,的数组{2,3,1,0,2,5,3},那么对应的输出是重复的数组2或者3。(n个元素,n种可能的取值)

解法一:先对数组进行排序,然后再查找排序后的数组中的重复元素



def selectedSort(lis):
for i in range(0, len(lis)):
minVal = lis[i]
minInd = i
#找出最小的元素
for j in range(i+1,len(lis)):
if minVal>=lis[j]:
minVal=lis[j]
minInd=j
#交换
lis[minInd]=lis[i]
lis[i]=minVal
return lis
lis=[8,5,3,3,7,6,3,9,1,8]
lis_order=selectedSort(lis)
print(lis)


 

解法二:开辟一个新数组B,每次扫描源数组A中的元素,如果不在B中,就加入B中,如果在B中,就找到一个重复的元素



lisA=[8,5,3,3,7,6,3,9,1,8]
def findDuplicates(lisA):
lisB = []
for i in lisA:
if i in lisB:
print("找到一个重复的元素:%d"%i)
break
else: #当前扫描的元素不在lisB中,就加入到lisB中
lisB.append(i)
continue
findDuplicates(lisA)


 

解法三:因为列表总共有n个元素,所有元素可能取到的元素有0~n-1,共n种。如果不存在重复的数字,那么排序后数字i将会出现在下标为i的位置。现在让我们重新扫描数组,

  • 当扫描到下标为i的数字时,首先比较这个数字(记为m)与i是否相等:
  • 如果是,继续扫描下一个元素,
  • 如果不是,则再拿它与第m个数字比较:
  • 如果它和第m个数字相同,就找到了一个重复的元素;
  • 如果不同,就将m与第m个数字互换。接下来继续重头开始,重复换这个比较。

 



lisA=[8,0,2,3,7,6,4,2,1,5]
def findDuplicates(lisA):

i=0
while i <len(lisA) and lisA!=[]:
m = lisA[i]
if m == i:    
i += 1
else:
if m == lisA[m]:
print('找到一个重复的元素:%d' % m)
break
else:
temp = lisA[i]
lisA[i] = lisA[m]
lisA[m] = temp
i = 0

findDuplicates(lisA)


 


 

题目二:

在一个长度为n+1的数组里的所有数字都在1~n范围内,所以数字中至少有一个数字是重复的。请找出数组中任意一个重复的数字,但是不能修改数组。例如,如果输入长度为8的数组{2,3,5,4,3,2,6,7},那么对应的输出是重复的数字2或3。(n+1个元素,n种可能的取值)

解法一:同上题解法二,开辟一个大小为n+1的新数组

解法二:避免使用O(n)的辅助空间。我们把取值空间[1,n]从中间的数字m分为两部分,前面一部分为1~m,后面一部分为m+1~n。如果数组中元素落在前面一部分的元素个数多于m个,那么数组中重复的元素一定落在前半区间;否则,数组中重复的元素一定落在后半区间。然后,我们可以继续将包含重复元素的区间一分为二,直到找到一个重复的元素。



lisA=[8,1,2,3,7,6,7,4,9,5,10]

def findDuplicates(lisA):
"""找到重复元素,返回True;否则,返回False"""
low=1
high=len(lisA)-1

while low<=high:
mid=(low+high)//2

#统计数组中落在前半部分区间中的元素的个数
count_low=0
for i in lisA:
if i in range(low,mid+1):
count_low+=1

#判断落在长度为1的区间中的数组元素个数
if high==low:
if count_low>1: #如果大于1,则找到重复的元素
return low
else:
break

#比较前半部分区间长度与落在该区间内元素的个数,决定将前半部分/后半部分区间继续一分为二
if count_low>(mid-low+1):
high=mid
else:
low=mid+1

return False

print(findDuplicates(lisA))


 

 



题目一:在一个长度为n的数组里的所有数字都在0~n-1的范围内。数组中某些数字是重复的,但是不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。例如,如果输入长度为7,的数组{2,3,1,0,2,5,3},那么对应的输出是重复的数组2或者3。(n个元素,n种可能的取值)

解法一:先对数组进行排序,然后再查找排序后的数组中的重复元素



def selectedSort(lis):
for i in range(0, len(lis)):
minVal = lis[i]
minInd = i
#找出最小的元素
for j in range(i+1,len(lis)):
if minVal>=lis[j]:
minVal=lis[j]
minInd=j
#交换
lis[minInd]=lis[i]
lis[i]=minVal
return lis
lis=[8,5,3,3,7,6,3,9,1,8]
lis_order=selectedSort(lis)
print(lis)


 

解法二:开辟一个新数组B,每次扫描源数组A中的元素,如果不在B中,就加入B中,如果在B中,就找到一个重复的元素



lisA=[8,5,3,3,7,6,3,9,1,8]
def findDuplicates(lisA):
lisB = []
for i in lisA:
if i in lisB:
print("找到一个重复的元素:%d"%i)
break
else: #当前扫描的元素不在lisB中,就加入到lisB中
lisB.append(i)
continue
findDuplicates(lisA)


 

解法三:因为列表总共有n个元素,所有元素可能取到的元素有0~n-1,共n种。如果不存在重复的数字,那么排序后数字i将会出现在下标为i的位置。现在让我们重新扫描数组,

  • 当扫描到下标为i的数字时,首先比较这个数字(记为m)与i是否相等:
  • 如果是,继续扫描下一个元素,
  • 如果不是,则再拿它与第m个数字比较:
  • 如果它和第m个数字相同,就找到了一个重复的元素;
  • 如果不同,就将m与第m个数字互换。接下来继续重头开始,重复换这个比较。

 



lisA=[8,0,2,3,7,6,4,2,1,5]
def findDuplicates(lisA):

i=0
while i <len(lisA) and lisA!=[]:
m = lisA[i]
if m == i:    
i += 1
else:
if m == lisA[m]:
print('找到一个重复的元素:%d' % m)
break
else:
temp = lisA[i]
lisA[i] = lisA[m]
lisA[m] = temp
i = 0

findDuplicates(lisA)


 


 

题目二:

在一个长度为n+1的数组里的所有数字都在1~n范围内,所以数字中至少有一个数字是重复的。请找出数组中任意一个重复的数字,但是不能修改数组。例如,如果输入长度为8的数组{2,3,5,4,3,2,6,7},那么对应的输出是重复的数字2或3。(n+1个元素,n种可能的取值)

解法一:同上题解法二,开辟一个大小为n+1的新数组

解法二:避免使用O(n)的辅助空间。我们把取值空间[1,n]从中间的数字m分为两部分,前面一部分为1~m,后面一部分为m+1~n。如果数组中元素落在前面一部分的元素个数多于m个,那么数组中重复的元素一定落在前半区间;否则,数组中重复的元素一定落在后半区间。然后,我们可以继续将包含重复元素的区间一分为二,直到找到一个重复的元素。



lisA=[8,1,2,3,7,6,7,4,9,5,10]

def findDuplicates(lisA):
"""找到重复元素,返回True;否则,返回False"""
low=1
high=len(lisA)-1

while low<=high:
mid=(low+high)//2

#统计数组中落在前半部分区间中的元素的个数
count_low=0
for i in lisA:
if i in range(low,mid+1):
count_low+=1

#判断落在长度为1的区间中的数组元素个数
if high==low:
if count_low>1: #如果大于1,则找到重复的元素
return low
else:
break

#比较前半部分区间长度与落在该区间内元素的个数,决定将前半部分/后半部分区间继续一分为二
if count_low>(mid-low+1):
high=mid
else:
low=mid+1

return False

print(findDuplicates(lisA))