昨天去面试花了一下午的时间,被问了很多问题,结果是达不到我的待遇要求而告终。
期间那个技术总监出了一道题说是考考逻辑,题目是这样的:有九个外观看起来是一摸一样的小球,但是其中有一个质量比其他的小球大,现给你一架天平如何找出那个质量大的小球?
应该算是比较简单的,但当时却没能想出比较好的解决办法而是想到最笨的那种:在天平的两端各放4个小球,如果平衡则剩余的那个就是质量大的那个,如果不平衡则把剩下的那个区替换天平上的小球,逐一替换,这样可能就要替换8次才能找出。知道这个答案肯定令对方不满意,可惜他也没给出一个比较的方法。
后来回到家又想了想,其实第一步考虑的是对的,先在天平的两端各放4个小球,如果平衡则剩余的那个就是质量大的那个,如果不平衡则把重的那端4个在分成两组分别放在天平两端,然后再把重的那端2个分别放到天平两端即可找出质量大的那个小球这样下来最多称3次便可找出。这个算法就像是递归,我们用js来表示
function search(bs){ // 主函数
var n = bs.length,tm,result;
n % 2 == 0 ? bs = bs:tm = bs.shift();
result = compare(split_2(bs));
result = result ? result:tm;
alert(result.quality);
}
function compare(z){ // 比较
var a = z[ 0 ],b = z[ 1 ],tem;
var x = 0 ,y = 0 ;
for ( var i in a)
x += a[i].quality;
for ( var p in b)
y += b[p].quality;
if (x == y) return false ;
tem = x > y ? a:b;
if (tem.length < 2 ){
return tem[ 0 ];
}
return arguments.callee(split_2(tem));
}
function split_2(arr){ // 分组
var a = [],b = [],len = arr.length;
if (len < 2 ) return arr[ 0 ];
for ( var i = 0 ;i < len / 2;i++){
a.push(arr[i]);
arr.shift();
}
b[ 0 ] = a;
b[ 1 ] = arr;
return b;
}
search(balls);
附:在写这段代码的时候遇到一个麻烦就是递归的时候没有 return 自身,导致递归链断裂而不能正确返回结果,下次使用递归的时候一定要小心了。
群里的朋友给出了更优算法,把9个小球分成三份,把小球数目相同的两份拿去称,如果平衡则质量大的小球在另外一组里,在把这组拿两个出来秤便可以得出质量大的那个;如果不平衡则把重的一端拿两个秤便可找出。只用2次秤就可完成。用js表示
function search(bs){ // 主函数
var result;
result = compare(split_3(bs));
return result.quality;
}
function compare(z){ // 比较
var a = z[ 0 ],b = z[ 1 ],tem;
var x = 0 ,y = 0 ;
for ( var i in a)
x += a[i].quality;
for ( var p in b)
y += b[p].quality;
if (x == y)
return z[ 2 ].length == 1 ? z[ 2 ][ 0 ]:arguments.callee(split_3(z[ 2 ]));
tem = x > y ? a:b;
return tem.length == 1 ? tem[ 0 ]:arguments.callee(split_3(tem));
}
function split_3(arr){ // 分组
var a = [],b = [],c = [],len = Math.floor(arr.length / 3);
if (len < 1 ){
a = arr.slice( 0 ,arr.length / 2);
b = arr.slice(arr.length / 2,arr.length);
return [a,b];
}
a = arr.slice( 0 ,len);
b = arr.slice(len,len * 2 );
c = arr.slice(len * 2 ,arr.length);
return [a,b,c];
}
alert(search(balls));