【问题标题】:Algorithm to find counterfeit coin amongst n coins从 n 枚硬币中找出假币的算法
【发布时间】:2017-01-10 05:14:12
【问题描述】:

所以这是仅使用天平在一组硬币中找到假币的经典问题。为了完整起见,以下是此类问题的一个示例:

一个众所周知的例子有九个(或更少)物品,比如硬币(或球),除了一个重量相同之外,在这个例子中它比其他的更轻——一个假币(一个古怪的球)。仅通过在秤上称重才能看出差异 - 但只能称量硬币本身。是否可以只用两次称重来隔离假币?

我们正在处理只有一枚硬币是伪造的并且我们知道它是怎么回事(即我们知道它更重/更轻)的情况。

我的问题是,对于N 一枚假币,是否有一种通用的有效算法可以解决此问题的通用版本。我一直在考虑它,到目前为止,如果N 的形式为3^k,那么您可以通过递归地将它们分成三个一组来在⌈log_3_(N)⌉ 中找到伪造品。这对所有 N 都是如此,而不仅仅是来自 3^k 的那些,如果是这样,我们能做得更好吗?

【问题讨论】:

  • 我投票结束这个问题,因为它属于programming.stackexchange.com 或maths.stackexchange.com
  • @DhruvPathak 解释。我在问我们可以使用的具体算法;这与stackoverflow有何关系。见hereherehere...
  • 你为什么把这个选为题外话?这是关于设计一种算法,该算法在其他网站上同样有效,并且可能更适合数学,但它也是这里的主题。

标签: algorithm


【解决方案1】:

除非您有任何关于输入的额外信息,否则⌈log_3_(N)⌉ 是您能找到的最好的。三组相同数量的硬币,将其中两组相互称重,您将看到三组中哪一组的重量较轻。递归地将相同的算法应用于最轻的组。 k^3 以上的任何剩余硬币也将保留以供后续回合使用。

【讨论】:

  • 你说的是一般情况。那么最好和最坏的情况是什么?
  • 对于随机输入,⌈log_3_(N)⌉ 是最好的、平均的和最差的复杂度。在最坏的情况下,我们会剩下 2 个硬币,我们无法检查,直到我们到达终点。这在最后最多添加了一个额外的比较。实际最坏情况的复杂度为⌈log_3_(N)⌉ * 2 + 1,用于保留额外的 2 个硬币。
【解决方案2】:

假设你有 N 个硬币。

制作 3 组硬币,每组包含 floor(N/3) 个硬币。如果有剩余硬币(N%3),将它们放在最后(3rd)组中。请注意,前 2 组的硬币数量相同。

称量第一组和第二组。如果它们不相等,那么我们必须从其中一组中找到罪魁祸首(假币)。所以我们的解决方案空间在第一次称重后减少到 N/3

如果它们相等,则假币出现在第 3 组中,最多 (N/3) + 2 个硬币

递归执行此操作,让我们在 ceil(log_3_(N)) 时间内找到伪造品

【讨论】:

    【解决方案3】:

    解决假币问题的Javascript代码:

    let coins = [3, 2, 3, 3, 3, 3, 3, 3, 3];
    let weightUsageCount = 0;
    var optimizeUsage = function (coins) {
      let n = coins.length;
      if (n < 1) {
        //If length is lower than 1, no coins are provided
        return -1;
      } else if (n == 1) {
        //If one coin left, it is the lighter coin
        printCoinInfo(coins[0]);
      } else {
        let set1 = coins.slice(0, parseInt(n / 2));
        let set2 = coins.slice(parseInt(n / 2), 2*(n/2));
        let set3 = coins.slice(2*parseInt(n/2), n);
    
        var coin = diffScale(set1, set2);
        if (coin == 0) {
          //Set 1 is lighter
          optimizeUsage(set1);
        } else if (coin == 1) {
          //Set 2 is lighter
          optimizeUsage(set2);
        } else {
          //Balanced
          optimizeUsage(set3);
        }
      }
    };
    
    
    var diffScale = function (coinSet1, coinSet2) {
      weightUsageCount++;
      let sum1 = coinSet1.reduce((a, b) => a + b, 0);
      let sum2 = coinSet2.reduce((a, b) => a + b, 0);
      
      if (sum1 < sum2) return 0;
      else if (sum2 < sum1) return 1;
      return -1;
    };
    
    var printCoinInfo = function(coin) {
      console.log("Array : "+JSON.stringify(coins)+ " | Total Coins : "+coins.length);
      console.log("Defect Coin Weight : "+coin);  
      console.log("Weight Scale Usage : "+ weightUsageCount+" Times");
    }
    
    optimizeUsage(coins);
    

    在此处查看 JSFiddle 演示:https://jsfiddle.net/ShashiBadhuk/odtyms5g/

    【讨论】:

      【解决方案4】:

      我用过这段代码,但有时它会关闭 1((:

      def how_many_measurements(n):
          import math
          if n<2:
              x = 0
          elif n >= 2 and n<=4:
              x = 1
          elif n>4 and n<12:
              x = 2
          else:
              x= math.ceil(math.log((2*n+1),3))
          return x    
      

      【讨论】:

      • 为什么减一?
      • 不确定。对于一些随机生成的硬币数量。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多