引言

今天面试,面试官问了一道经典的问题:

一个5L的杯子和一个3L的杯子,水无限,如何得到4L水?

这个问题非常经典,经典到我下意识就能回忆起解法:

  1. 将5L杯子装满水,然后倒满3L的杯子,此时5L杯子里有2L水
  2. 将3L杯子清空
  3. 将5L被子里剩余的2L水导倒入3L杯子中
  4. 5L杯子取水,倒入3L杯,此时5L杯中就有4L水了

我们可以用表格来表达每一步的状态:

步骤操作3L杯内水的体积5L杯内水的体积
15L杯取水0L5L
25L杯倒入3L杯3L2L
33L杯清空0L2L
45L杯倒入3L杯2L0L
55L杯取水2L5L
65L杯倒入3L杯3L4L

问题很简单,很好解决,接下来面试官问出了一个变种:杯子容量变成 7L 和 11L,取出 2L 水。

解法其实也不变,大杯接水倒小杯。接下来的表格中我们会用(容量)L 代表杯子,-> 代表水的流动:

步骤操作7L杯11L杯
1-> 11L0L11L
211L -> 7L7L4L
37L ->0L4L
411L -> 7L4L0L
5-> 11L4L11L
611L -> 7L7L9L
77L ->0L9L
811L -> 7L7L2L

随后,面试官问出了终极难题:什么情况下这个问题无解?

证明

这个问题我在网上没有找到它的名字,我就将其命名为“双杯取水问题”好了。我们先只考虑我们目前的解法——即将大杯中的水倒入小杯,最后取得指定容量的水——这种情况下,会有那些情形是无解的。

我们假设大杯容量为M,小杯容量为N,每次我们能取出的特定容量为:

  1. M - N
  2. M - (N - (M - N)) = 2(M - N)
  3. M - (N - 2(M - N)) = 3(M - N)
  4. M - (N - 3(M - N)) = 4(M - N)

不难看出,每一步我们能取出的特定容量都为 n(M - N),考虑每次我们还会将 N 的整数倍倒掉,最后的结果是 n(M-N) mod N。我的直觉告诉我,这个问题的解和 M - N 与 N 的最大公因数有关,如果最大公因数不为1,则会有无解的情况。要证明也不是很困难,我们画一个数轴就可以得到。假设最大公约数为a,M - N 为 b,则 nb 在数轴上一定会落到 a 的倍数上,而nN也一定会落到 a 的倍数上,所以 nb 减去 N 的整数倍后还是会落到 a 的整数倍上。在 a != 1 的情况下,a 的整数倍之间的空隙就是我们要找的无解的解。

换个角度

把 N 和 M 的整数倍都画在数轴上,也能很容易得出,用小杯往大杯倒水也是一样的效果,他们在数学上是等价的。这个问题的数学本质是在问 nN 与 mM 之间的差值。

当然,我们也很容易看出,当 M 和 N 都是整数的时候,我们是取不出小数升的水的。

标签: none

添加新评论