任务描述
依然是分治算法。
相关知识
找假币问题是一个比较简单且典型能够体现计算思维的问题。假设现在有n(n>=2)枚硬币,已知其中一枚为假币,且知道假币的重量是比真币轻的,请思考如何用分治思想解决该问题。
算法原理
本次实验中我们采用二分法解决假币问题。二分法是一个非常典型的分治思想的应用。
- 如果n是偶数,将n个硬币平均分成两份,直接比较这两份硬币的重量,假币在重量较轻的那份硬币中,继续对重量较轻的那一份硬币使用二分法,直到找出假币;
- 如果n是奇数,则随意取出一种的一枚硬币,将剩下的n-1枚硬币等分成两份。如果这两份硬币重量相同,则随机取出的那枚硬币即为假币;否则,按照硬币数为偶数是的处理办法继续执行算法。
算法实现
前提假设:假币比真币轻,真币重量一致。
如果没有假币,索引和重量位置均为-1。
测试说明:
测试输入:
3,3,3,3,3,3,3,2,3
预期输出:position is: 7, weight is: 2.
看懂了就写完了
函数ac代码
def f_c(a, arr): # a为索引,l列表,最终函数运行结果是假币的位置索引和假币的重量。
x = len(arr) # x继承个数
# print(a+1, arr) #打印索引和列表,报告检查
if x == 1: # 单列表
return a # ,返回序列
if x % 2 == 1: # 奇数长案例
x = x - 1 # x继承尾序列,随便拿了最后一个
y = 1 # 状态变量随便抽一个
else: # 偶数长
y = 0 # 直接分
# 以上为第一批选择结构
# 分割
if (sum(arr[:x // 2])) < sum(arr[x // 2:x]): # 前半段 小于 后半段
return f_c(a, arr[:x // 2]) # 递归调用 ,前半段再分
elif (sum(arr[:x // 2])) > sum(arr[x // 2:x]): # 前大于后
return f_c(a + x // 2, arr[x // 2:x]) # 递归后半段
else: # ,上面应该是控制了补集关系,前后相等.
if y == 0: # 平分状态
return -1 # 返回负一,无假币
else: # 随便拿了最后一个
if arr[x] < arr[0]: # 鉴定为假
return a + x # 返回序列
else: # equal
return -1 # 无假币
主函数边界修正
if __name__ == '__main__':
li = input().split(',') # get char
a = [int(x) for x in li] # be int
n = f_c(0, a) # get it x
if n!=-1:
print('position is: %d, weight is: %d.' % (n, a[n]))
else:
print('position is: %d, weight is: %d.' % (n, -1))
原题有代码图
是一道阅读理解
增加更完备的描述,提供代码,减少外链,增加投票来和读者互动。