N块银币中有一块不合格,已知不合格的银币比正常银币重。现有一台天平,请利用它找出不合格的银币,并且要求使用天平的次数最少。
def sum(left,right):
num=0
for i in range(left,right+1):
num=list1[i]+num
return num
def search(left,right):
mid=(left+right)//2
global f
if left==right-1:
f = f + 1
if list1[left]>list1[right]:
return left
else:return right
if (right-left)%2==0:#说明是奇数
f = f + 1
if sum(left,mid-1)>sum(mid+1,right):
return search(left,mid-1)
elif sum(left,mid-1)<sum(mid+1,right):
return search(mid+1,right)
else :return mid
else :#说明是偶数
f = f + 1
if sum(left,mid)>sum(mid+1,right):
return search(left,mid)
else :
return search(mid+1,right)
if __name__ == '__main__':
N = int(input("请输入银币总数:"))
s = int(input("请输入不合格银币所在位置:"))
left = 1
right = N
f = 0
list1 = [1 for i in range(N + 1)]
list1[s] = 2
flag=search(1,N)
print(f"不合格银币位置:{flag}")
print(f"比较次数:{f}")
下面是使用三分法的代码,最后比较一下使用二分和三分的优缺点。
def sum(left,right):
num=0
for i in range(left,right+1):
num=list1[i]+num
return num
def search(left,right):
mid=(right-left+1)//3
k=(right-left+1)%3
global f
if left==right:
f=f+1
return left
elif left==right-1:
f=f+1
if list1[left]>list1[right]:
return left
else :return right
f = f + 1
if sum(left,left+mid-1)>sum(left+mid,left+mid*2-1):
return search(left,left+mid-1)
elif sum(left,left+mid-1)<sum(left+mid,left+mid*2-1):
return search(left+mid,left+mid*2-1)
elif sum(left+mid*2,left+mid*3-1)>sum(left,left+mid-1):
return search(left+mid*2,left+mid*3-1)
else:
if k==1:
return right
elif k==2:
f=f+1
if list1[right-1]>list1[right]:
return right-1
else :return right
if __name__ == '__main__':
N = int(input("请输入银币总数:"))
s = int(input("请输入不合格银币所在位置:"))
left = 1
right = N
f = 0
list1 = [1 for i in range(N + 1)]
list1[s] = 2
flag=search(1,N)
print(f"不合格银币位置:{flag}")
print(f"比较次数:{f}")
粗略的发现,三分法在银币总数大时的比较次数更少,更适合。