问题:
有n个硬币,其中有⼀枚是假币,假币⽐真币要轻,现有⼀天平,通过⽐较找出假币。
三分法思路:
1.将硬币分为三堆,每堆按照n/3向上取整个硬币来分配(主要分配前两堆,第三堆就是剩下的)
2.⽐较第⼀堆和第⼆堆硬币重量
若重量相等,则在第三堆中找假币,重复第⼀步
若第⼀堆⽐第⼆堆重,则在假币在第⼆堆中,去第⼆堆中找假币,重复第⼀步
若第⼆堆⽐第⼀堆重,则在假币在第⼀堆中,去第⼀堆中找假币,重复第⼀步
三分递归解法:
def findFalseCoin(coins, idxStart, iLength):
if iLength == 1:
return idxStart
n = ceil(iLength / 3)
wPart1 = sum(coins[idxStart:idxStart + n])
wPart2 = sum(coins[idxStart + n:idxStart + 2 * n])
wPart3 = sum(coins[idxStart + 2 * n:iLength])
if wPart1 < wPart2:
return findFalseCoin(coins, idxStart, n)
elif wPart1 > wPart2:
return findFalseCoin(coins, idxStart + n, n)
else:
return findFalseCoin(coins, idxStart + 2 * n, iLength-2*n)
if __name__ == '__main__':
coins = [100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100]
for i in range(len(coins)):
coinsCopy = coins[:]
coinsCopy[i] = 99
r = findFalseCoin(coinsCopy,0,len(coinsCopy))
print(f'False coin idx:{r}, weight:{coinsCopy[r]}')
三分非递归解法:
def findFalseCoin(coins):
# 查找范围:从idxStart下标开始的iLength个硬币
idxStart, iLength = 0 , len(coins)
while True:
if iLength == 1:
return idxStart
n = ceil(iLength / 3)
wPart1 = sum(coins[idxStart:idxStart + n])
wPart2 = sum(coins[idxStart + n : idxStart + 2 * n])
wPart3 = sum(coins[idxStart + 2 * n : iLength])
if wPart1 < wPart2:
idxStart, iLength = idxStart, n
elif wPart1 > wPart2:#在第二堆
idxStart, iLength = idxStart + n , n
else:
idxStart, iLength = idxStart + 2 * n , iLength - 2 * n
if __name__ == '__main__':
coins = [100] * 11
for i in range(len(coins)):
coinsCopy = coins[:]
coinsCopy[i] = 99
r = findFalseCoin(coinsCopy)
print(f'False coin idx:{r}, weight:{coinsCopy[r]}')