称球问题的通用解法

来源:互联网 发布:网站关键词优化查询 编辑:程序博客网 时间:2024/04/29 11:40

最近看了个算法题 据说还是google面试题之一,大意是:八个球已知其中有一个是偏重的,问最少几次称出来?

之前我在网上还有个更难的,大意是:13个球已知其中有一个重量异常(重或者轻),给一个天平3次称出那个异常球。

 

仔细想想 其实这两个题目是有紧密联系的。13球问题的解答需要用到8球问题的解法。

先看看 8球与13球问题的解法:

 

8球:

先将球8个球分成3堆:3,3,2的形式(3,3是代表在天平两端的球数)。

1、称一次找出重的一边(平衡就只要再称剩下两个中重的一个即可,2次搞定);

2、重的一边三个球,取出两个称:如果平衡则是另一个,不平衡就是重的那个(2次搞定)。

所以,8个球出重的一个球需要两次。

 

13球:

把球分成三堆:4,4,5的形式。(5,5,3的分法需要4次)。

 

1、平衡将5个球分成两堆(2,3);

1.1、将分好的三个球替换天平上任意一端得三个球;

1.2、查看天平状态,如果发生偏移则说明异常球就在这三个中,而且可以知道是轻还是重;如果没有发生偏移则说明在另外两个球中;

1.2.1、如果在三个球中间,且知道轻重,则任意取两个球再称一次就能找出异常球;

1.2.2、如果在两个球中不知道轻重,则取正常球一个,再在两个球中任意取一个称;如果平衡则是两个球中的另一个;如果不平衡则是除去正常球以外的另一个;

平衡的情况只要称三次。

 

2、不平衡则在5个正常球中取三个与天平上重的一侧(轻的一侧也行)的4个球中的3个交换

 ;然后将重的一侧4个球中没有交换的一个球与轻的一侧的4个球中任意一个互换;再称;

这个时候可能出现3种状态:(注意重的一侧的球全部发生了交换!)

2.1、天平保持不变:则说明异常球在天平轻的一侧的没有被交换的3个球之中;这样就再称1次便可找出异常球;

2.2、天平平衡:则说明异常球在换下天平的三个球中;而且是重球,这样再称1次就能解决;

2.3、天平发生倾覆:则说明异常球在左右互换的两个球中,而且不知道异常球的轻重;这个时候可以取两个球中的一个与一个正常球称;如果平衡则是两个球中的另一个球;如果不平衡则是正常球以外的另一个。

所以可以看出两种情况都最多只要3次就能搞定。

 

那么有什么联系吗?

1、称13个中异常的时候在第一次称不平衡的条件下,互换的过称实际上是将球的轻重做了区分(因为天平两边的交换其实只铁定只要再称一次便可);将异常球的轻重得出来而且锁定了范围。这时,问题就退化为“8球问题”了;

2、如果天平平衡,则异常球肯定在天平下的剩余的球。这个时候将剩下的球分半,一半与天平上的正常球交换,一半不动。其实是一种变形的“13球”问题。因为,分半以后跟交换以后的正常球正好变异成一个球数为(N/2上取整+1)个球的新“13”球问题的称完一次时的情况。(将分开的球看做天平两边不平衡的两端,交换下来的球看着做天平下的正常球!)

而且肯定称的次数会比(N/2上取整+1)少1次,所以这样一来这种情况的称数是:1+(Recusive F(N/2上取整+1)个球的次数-1)次=F(N/2上取整+1)-F(N)为计算13球问题的函数。根据常识,F(N)>=F(N/2上取整+1)。所以其实这种情况是可以不考虑的!

综合1,2可以看出,13球问题其实是分组处理以后的8球问题。

 

这一来可以得出解N个球中称出一个异常球的通用解法:

将N个球分成3堆,保证形成M,M,M或者M+1,M+1,M或者M,M,M+1的分法(肯定是可以的,因为任何数除3余数只能是0,1,2,对应上面三种情况。因为这样能保证重的那边或者轻的那边的球都被交换掉!)。

令解“8球”问题的函数为F(X);则解N球1个异常球的方法是G(x)=2+F(M)。F(X)是一个递归函数,每一步都是贪心的。(加2表示做F()之前其实已经称了2次了)

这样一来G(x)=2+F(M)很简单的形式,解决了复杂的问题。

 

原创粉丝点击