2006年12月23日土曜日

经典面试问题:12小球问题算法

IQ:

12 颗玻璃球大小一样, 不知道哪一颗重了, 还是轻了. 请用天平秤秤3, 把其中的一颗重量不均匀的玻璃球取出来!

高手的给的答案

先把小球平均分成三组每组4个。

1)第一次把其中两组放到天平两边,若平衡,这种情况较简单,这里不说了,

2)若不平衡,假定轻的是左边的四个小球,编号为1234号;重的是右边,编号为5678,第三组(没放在天平的)编号为912

3)第二次把1259放在天平左边,34610放右边若平衡,则不同的小球是78,而且比一般球重,第三次容易区分。

4)若天平还是左轻右重, 则不同的小球是126之一,第三次也容易区分,只需把12秤出轻的便是,否则是6,若天平变为左重右轻,则不同的小球为345之一,方法与上同。

高手的给的答案

先把小球平均分成三组每组4个。

1)第一次把其中两组放到天平两边,若平衡,这种情况较简单,这里不说了,

2)若不平衡,假定轻的是左边的四个小球,编号为1234号;重的是右边,编号为5678,第三组(没放在天平的)编号为912

3)第二次把1259放在天平左边,34610放右边若平衡,则不同的小球是78,而且比一般球重,第三次容易区分。

4)若天平还是左轻右重, 则不同的小球是126之一,第三次也容易区分,只需把12秤出轻的便是,否则是6,若天平变为左重右轻,则不同的小球为345之一,方法与上同。

正解。不过此题答案不唯一。大家可以继续想。

核心思路是,每次称重,不管天平平衡与否,都能尽可能多的排除掉一些可能。

和海盗问题一样,这也是MS前几年的面试题之一

太容易了 分成三组!

A{a0,a1,a2,a3}

B{b0,b1,b2,b3}

C{c0,c1,c2,c3}

if(A==B)

{

D' = {c0,c1,c2}

if ( D' = = {a0,a1,a2} ) {

c3 is bad ball;

} else if( D' > {a0,a1,a2} ){

D" = {c0 ,a0};

D"" = {c1,a1};

if( D" = = D"" ){

c2 is bad ball;

}else{

if( D" > D"" )

c0 is bad ball;

else

c1 is bad ball;

}

}else if( D' < {a0,a1,a2}) {

D" = {c0 ,a0};

D"" = {c1,a1};

if( D" = = D"" ){

c2 is bad ball;

}else{

if( D" > D"" )

c1 is bad ball;

else

c0 is bad ball;

}

}

if(A > B){

D' = {a0,a1,b2,c3}; ‘选球过程中还有a3,b3,b1没有选

D" = {b0,c1,a2,c0};

if( D' == D" ){

{a3,b3}{c0,c1}比较

if( > )

a3 is bad ball

if( < )

b3 is bad ball

if( = )

b1 is bad ball

}

if(D > D" ){ ‘假设坏球大,那么就在a0,a1当中;假设坏球小,那么就在b0

坏球在a0,b0,a1之间

{a0,b0}{c0,c1}比较

... if( > )

a0 is bad ball

if( < )

b0 is bad ball

if( = )

a1 is bad ball

}

if(D'<>

a2,b2任一,和标准c0比较 ‘假设坏球大,那么就在a2当中;假设坏球小,那么就在b2

if a2>c0

a2 is bad ball

else

b2 is bad ball

}

}

if(A <>

D' = {a0,a1,b2,c3}; ‘选球过程中还有a3,b3,b1没有选

D" = {b0,c1,a2,c0};

if( D' == D" ){

{a3,b3}{c0,c1}比较

if( > )

b3 is bad ball

if( < )

a3 is bad ball

if( = )

b1 is bad ball

}

if(D < style=""> ‘假设坏球小,那么就在a0,a1当中;假设坏球大,那么就在b0

坏球在a0,b0,a1之间

{a0,b0}{c0,c1}比较

... if( > )

b0 is bad ball

if( < )

a0 is bad ball

if( = )

a1 is bad ball

}

if(D'> D" ){

a2,b2任一,和标准c0比较 ‘假设坏球大,那么就在b2当中;假设坏球小,那么就在a2

if a2>c0

b2 is bad ball

else

a2 is bad ball

}

}

这题我两年关就做过了.我来回答.开始同ziqing_1_2_3一样

先把小球平均分成三组每组4个。

分别是 组一, A.B.C.D

组二, 1.2.3.4

组三, a.b.c.d

先用第一组和第二组称.平衡就不用说了(重或轻的球在组三中).

先假设.组一重.组二轻.

第一组和第二组不平衡.说明组一和组二中有一个球或重或轻.

再用A.B.1 C.D.2去称(这后面就要用逻辑去想了) 平衡那是在3.4球不同.

不平衡.

1.平衡有没有出现交换.那么 A.B 中有一球重. 2

2.平衡发生交换那么 C.D. 中有一球重. 1

再用A.2C.1a.b.就可以推理出不同重量的球

3个以下 三的一次方 1算出 1V1

9个以下 三的二次方 2算出 3V3 1v1

27个以下 三的三次方 3算出 9V9 3V3 1v1

81个以下 三的四次方 4算出 27v27 9V9 3V3 1v1

.....

以下类推..

12个的合理算法,分为9,3,0

9中的话,2次可算出 (9再分3,3,3 )

3中的话,1次可算出

12个最多三次可算出结果

以上所有对半分的答案肯定不是最合理的,些题考的只是一个算法,12只是一个特例,有没有考虑过:27,24,81....20003333个的情况呢...

3的次方是此题的规律...

经典面试问题:12小球问题算法

作者:成晓旭

1 问题描述:

现有12个外形相同的小球,只有其中一个小球质量不同(不能确定较重还是较轻),请用天平找出是哪个小球不同,而且还要找出究竟是轻是重?条件:只能称三次。

此问题已经在网上广为流传,相信很多朋友早有自己的解答方法。本人在2002年底听到此问题,煞费心思终到此解,之后,向我了解问题解决方法及过程的朋友络绎不绝;所以索性做了个软件工具来演示自己的解答思路和过程。

温馨提示:4年前的程序写得很垃圾,用Java重新实现的版本已在计划之中,敬请继续关注我的Blog

2 软件设计

其实,这类软件没有什么设计可言,本质就是一个核心算法的实现。所以,这里的设计,只是我从Rose中逆向工程后生成的文档组织而成。

其实,这个程序中含有大量的OPP的痕迹,也没有真正看到设计模式的应用;偶尔回头看看自己4年前写的代码,再回想起自己当初完成此程序的“莫大成就感”!真是幼稚之极!

2.1、包设计

程序共设计为3个包:

Common包:小球问题的算法封装,里面采用面向过程的实现方式,没有任何类。主要对外提供的方法有:

//清除画面方法

procedure ClearCanvas(aCanvas: TCanvas; aRect: TRect);

//小球问题条件设置方法

procedure Draw_Ball_Config(

AllBall:array of TC_Ball;

ACanvas:TCanvas;

aClearRect: TRect;

bShowTrace:Boolean);

//小球问题解决方法

procedure Serach_Error_Ball(

AllBall:array of TC_Ball;

ACanvas:TCanvas;

aClearRect: TRect;

bShowTrace:Boolean);

BallType包:小球问题演示程序的显示绘制封装,主要包括与显示绘制相关的结构和类,以及一些过程和函数。

BMani包:小球问题的界面显示类,演示界面的控制、业务方法的调用、处理结果的呈现。

2.2、主要类简介

BallType包中的界面绘制:

TC_Ball//小球问题:小球抽象数据类型

TC_SearchBall//小球问题:被寻找的目标小球抽象数据类型

TC_CmpPara//小球问题:一次比较的参数的抽象数据类型

TC_Ball_Class//小球问题:小球抽象类

TC_Balance//小球问题:天平抽象类

TC_Compare//小球问题:天平比较一次抽象类[行为抽象]

TC_Ball_Problem//小球问题抽象类<2003-11-14至今未被使用,是为方法的通用性而设计>

核心的业务类关联视图:其实从这张乱如蛛网的依赖关系图中,足以说明设计之丑陋了。

0 件のコメント: