当前位置: 面试刷题>> 称重问题 (经典算法题500道)


### 题目描述补充 **称重问题**: 给定一组外观相同的硬币,但其中有一个是重量异常的(可能是更轻或更重),你只有一个天平,没有其他测量工具。问最少需要称重几次,才能确保找出这个异常的硬币,并且确定它是比正常硬币更轻还是更重? 假设总共有 N 个硬币,其中 N 是大于或等于 3 的奇数。 ### 解题思路 对于 N 个硬币的问题,我们可以采用分治策略。将硬币分为三组,每组数量尽可能相等(对于奇数 N,其中两组数量相同,第三组多一个)。 1. 第一次称重:选择两组数量相同的硬币进行称重。 - 情况 A: 如果两边平衡,说明异常硬币在未称重的那组中。 - 情况 B: 如果不平衡,说明异常硬币在称重的两组中。 2. 第二次称重(对于情况 A):从未称重的那组硬币中继续分治。 - 将这组硬币再次分为三小组(尽量平均),选择两组进行称重。 - 重复上述逻辑,直到找到异常硬币。 3. 第二次称重(对于情况 B):从之前称重的两组中选择看起来较轻或较重的那组(取决于第一次称重的结果),并将这组硬币分为三小组(尽量平均),选择两组进行称重。 - 如果这两组仍然不平衡,说明异常硬币在其中,并且我们可以知道异常硬币是更轻还是更重。 - 如果这两组平衡,说明异常硬币在之前未称重的那组中,且异常硬币的重量与这次称重中使用的硬币相反(即如果这次称重是找轻的,那么异常硬币是重的,反之亦然)。 4. 重复步骤 2 和 3,直到找到异常硬币。 ### 示例代码 由于篇幅限制,这里只给出 Python 的代码示例: ```python def find_fake_coin(coins, lighter=True): def weigh(group1, group2): if sum(group1) < sum(group2): return -1 # group1 轻 elif sum(group1) > sum(group2): return 1 # group1 重 else: return 0 # 平衡 def find_in_group(group, lighter): n = len(group) if n == 1: return group[0], (lighter and -1 or 1) # 返回硬币及其是轻是重 third = n // 3 group1, group2, group3 = group[:third], group[third:2*third], group[2*third:] result = weigh(group1, group2) if result == 0: return find_in_group(group3, not lighter) else: return find_in_group(group1 if result == (1 if lighter else -1) else group2, lighter) return find_in_group(coins, lighter) # 示例使用 coins = [1, 1, 1, 1, 2] # 假设第5个硬币更重 fake_coin, is_lighter = find_fake_coin(coins, lighter=False) print(f"异常硬币索引: {coins.index(fake_coin)}, 是否更轻: {'否' if is_lighter == 1 else '是'}") ``` 注意:这里的实现假设硬币的重量差异可以直接通过求和来体现,实际中可能需要使用更精确的天平测量。另外,索引是基于 0 的,并且代码中 `lighter` 参数用于指定是寻找更轻的硬币还是更重的硬币(这里设置为 `False` 表示寻找更重的)。 **码小课**网站中有更多关于算法和数据结构的内容分享,欢迎大家学习交流。
推荐面试题