使用数组模拟假硬币

时间:2016-09-25 17:57:48

标签: algorithm recursion

有70枚硬币,其中有一枚假硬币。需要在最小称量数量下检测假币。你只有一个秤,你知道假币很轻。

我不确定下面的问题模拟是对还是错,即在数组中表示它并按照我在代码中进行的比较。我试图用一个包含所有一个数组的数组来模拟它,除了一个被认为是伪币的零。以下是我的代码。如果我弄错了,请告诉我。

如果有人可以证明/解释为什么3路除法在简单数学中更好,那将会非常有用。

以下代码的伪代码:

INPUT    : integer n

if n = 1 then
   the coin is fake
else
   divide the coins into piles of A = ceiling(n/3), B = ceiling(n/3),
       and C = n-2*ceiling(n/3)
   weigh A and B
   if the scale balances then
      iterate with C
   else
      iterate with the lighter of A and B

代码:

import random

def getmin(data, start, end, total_items):
    if total_items == 1:
        #for sure we have a fake coin
        return (0, start)
    elif total_items == 2:
        if data[start] > data[end]:
            return (1, end)
        elif data[start] < data[end]:
            return (1, start)
    else:
        partition = total_items/3
        a_weight = sum(data[start:start+partition])
        b_weight = sum(data[start+partition:start+2*partition])
        c_weight = sum(data[start+2*partition:end])
        if a_weight == b_weight:
            result = getmin(data, start+2*partition, end, end-(start+2*partition))
            return (1+result[0], result[1])
        else:   
            if a_weight > b_weight:
                result = getmin(data, start+partition, start+2*partition, partition)
                return (1+result[0], result[1])
            else:
                result = getmin(data, start, start+partition, partition)
                return (1+result[0], result[1])

n = int(raw_input())
data = [1]*n
data[random.randint(0, n-1)] = 0
total_weighing, position = getmin(data, 0, len(data), len(data))
print(total_weighing, position)

2 个答案:

答案 0 :(得分:2)

此算法的复杂性为 O(log 3 N),因为在每次迭代中将问题大小减少到1/3。复杂性 O(log 3 (n)) == O(log 2 (n)) = = O(log 10 (n))因此,如果将问题大小除以3或10,则无关紧要。 only 更好的复杂性是 O(1),这意味着无论问题的大小,您都可以在固定数量的操作中找到假币,这是不太可能的。

请注意,在此算法中,我们假设我们可以在O(1)中找到一系列元素的总和,否则算法的复杂度为O(n)。

答案 1 :(得分:1)

你问“为什么三向分割在简单数学方面更好”。比什么更好?在这个问题中,它是最好的解决方案,因为它在最少的称重中实现了答案。平凡秤的属性产生三个基本结果:左侧较重,右侧较重,且重量相等。这是一个三向决策,因此信息理论产生的最佳算法是在每个阶段将对象分成三个(如果你能实际实现它)。

你需要4次称重才能获得28-81个硬币。

幸运的是,您的问题可以进行详尽的测试。 上面的代码执行一次随机测试。这对初学者来说没问题,但只有70个案例要检查,我建议你全部尝试。将主程序包裹在范围内的循环中(70),如下所示:

n = 70
for bad_coin in range(70):
    data = [1]*n
    data[bad_coin] = 0
    total_weighing, position = getmin(data, 0, n, n)
    print ("trial", bad_coin)
    if total_weighing != 4:
        print ("Wrong number of weighings:", total_weighing)
    if position != bad_coin:
        print ("Wrong ID:", position)

这将很快显示您的程序中所分配的70个硬币的任何错误。

BTW,如果您对该功能感到满意,请将 if 语句替换为断言

相关问题