Lab-P3-分治

第一关:分治法

任务描述

编写程序,实现从屏幕输入列表A的值,然后通过调用min_max()函数计算所输入的列表A的最小值和最大值。

算法原理介绍

用分治法同时求n个数a1​,a2​,...,an​中的最小值Min(1, n)和最大值Max(1, n)的基本思想是:

  1. 要求Min(1, n)和Max(1, n),可以先求得Min(1, n/2)和Min(n/2+1, n)以及Max(1, n/2)和Max(n/2+1, n),Min(1, n/2)和Min(n/2+1, n)中较小的就是Min(1, n),Max(1, n/2)和Max(n/2+1, n)中较大的就是Max(1, n)……直到要求Min(1, 1)和Max(1, 1),……,Min(n,n)和Max(n,n)。
  2. 根据Min(i, j)和Max(i, j)的定义可知:Min(1, 1)= Max(1, 1) =a1,……,Min(n, n)=Max(n, n)=an。
  3. 知道了Min(1, 1)和Max(1, 1),……,Min(n, n)和Max(n, n),通过分别比较Min(1,1)和Min(2,2),Max(1,1)和Max(2,2)可以得到Min(1, 2)和Max(1, 2)……直到得到Min(n-1, n)和Max(n-1,n);同理通过分别比较Min(1,2)和Min(3,4),Max(1,2)和Max(3,4)可以得到Min(1,4)和Max(1,4)……直到得到Min(n-3,n)和Max(n-3,n)……直到得到Min(1,n)和Max(1,n)。

注意事项

本节内容中仅可以调用下列两个函数:

1. min(a, b)--返回a和b中较小的元素

2. max(a, b)--返回a和b中较大值元素

编程要求

根据提示,在右侧编辑器补充代码,计算并输出列表的最大值和最小值。

测试说明

测试输入:

2,3,4,4.5,65.7

预期输出:

Minimum and Maximum: 2,  65.7

def min_max(a):
    # # 参数a为列表,编写分治法函数,返回a的最大值和最小值
    # # 注意,有两个返回值
    if len(a) == 1:
        return a[0], a[0]
    elif len(a) == 2:
        return min(a), max(a)
    m = len(a) // 2
    lmin, lmax = min_max(a[:m])
    rmin, rmax = min_max(a[m:])
    return min(lmin, rmin), max(lmax, rmax)


if __name__ == '__main__':
    # #编写代码,输入列表A,A列表中的都是数字
    A = [eval(i) for i in input().split(",")]
    # #输入A的的最大值和最小值
    # #下面这行代码不用修改哦~
    print("Minimum and Maximum: %g, %g" % (min_max(A)))

第二关:找假币问题

任务描述

依然是分治算法。

相关知识

找假币问题是一个比较简单且典型能够体现计算思维的问题。假设现在有n(n>=2)枚硬币,已知其中一枚为假币,且知道假币的重量是比真币轻的,请思考如何用分治思想解决该问题。

算法原理

本次实验中我们采用二分法解决假币问题。二分法是一个非常典型的分治思想的应用。

  1. 如果n是偶数,将n个硬币平均分成两份,直接比较这两份硬币的重量,假币在重量较轻的那份硬币中,继续对重量较轻的那一份硬币使用二分法,直到找出假币;
  2. 如果n是奇数,则随意取出一种的一枚硬币,将剩下的n-1枚硬币等分成两份。如果这两份硬币重量相同,则随机取出的那枚硬币即为假币;否则,按照硬币数为偶数是的处理办法继续执行算法。

编程要求

这一关比较特殊,要求你对你的每一行代码进行注释,说明它的用途,最终函数运行结果是假币的位置索引和假币的重量。

如果没有假币,索引和重量位置均为-1。

测试说明

测试输入:

3,3,3,3,3,3,3,2,3

预期输出:

position is: 7 ,weight is: 2.

# # 全部都自己写8
def find_coin(a, L):
    x = len(L)  # 获取L的长度,即硬币的总数
    if x == 1:  # 当硬币的数量为一时,就不用找了
        return a  # 直接返回a
    if x % 2 == 1:  # 当数量是奇数时
        x -= 1  # 舍弃最后一个硬币
        y = 1  # 记有一个硬币多余
    else:  # 否则
        y = 0  # 记为没有硬币多余
    if sum(L[:x // 2]) > sum(L[x // 2:x]):  # 如果前一半硬币质量的总和大于后一半硬币质量的总和
        return find_coin(a + x // 2, L[x // 2:x])  # 用同样的方法再次比较前一半硬币和后一半硬币的质量
    elif sum(L[:x // 2]) < sum(L[x // 2:x]) and y == 1:  # 如果前一半硬币质量的总和小于后一半硬币质量的总和
        return find_coin(a, L[:x // 2])  # 用同样的方法再次比较前一半硬币和后一半硬币的质量
    else:  # 如果两者质量相等
        if y != 0:  # 如果有多余的硬币
            if L[0] > L[x]:  # 如果第一个硬币的质量大于我们一开始剔除的硬币的质量
                return x  # 那么我们就返回最后一个硬币的位置
            else:  # 否则
                return -1
        else:  # 如果没有多余的硬币
            return -1


L = [int(i) for i in input().split(",")]
a = 0
m = find_coin(a, L)
if m != -1:
    print(f"position is: {m}, weight is: {L[m]}.")
else:
    print("position is: -1, weight is: -1.")

  • 25
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

在远方的眺望

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值