首先说说上下文:
http://www.cnblogs.com/beginor/archive/2009/04/27/1444844.html
http://www.cnblogs.com/ilovemeyou2000/archive/2009/04/29/1445797.html
这道"有趣"的面试题是:甲乙两地相距100公里,有一辆火车以每小时15公里的速度离开甲地直奔乙地,另一辆火车以每小时20公里的速度从乙地开往甲地。如果有一只鸟,以30公里每小时的速度和两辆火车同时启动,从甲地出发,碰到另一辆车后返回,依次在两辆火车来回飞行,直到两辆火车相遇,请问,这只小鸟往返了多少次?
首先说这个题,我觉得出的并无任何不严谨的地方,也没有能明显让人误解的地方。按照通常的表述,显然题意是忽略鸟的转身时间,忽略鸟的身长,把鸟和火车头抽象成三个点。如果非要考虑鸟的转身时间和身长,我觉得有故意曲解的嫌疑。任何一个应用问题都有隐含的忽略条件,答题者如果要求应用题表述无限精确滴水不漏,是不可能的。所以我觉得有些关于量子物理的言论就没有必要了。如果硬要钻牛角尖,还可以说火车道不是严格的直线,可以说鸟并非匀速直线运动,可以说根据相对论速度和距离、时间应该遵守洛伦兹变换而非伽利略变换。
然后是解法,按照原意,鸟往返了无限多次,可以用数学归纳法证明:
假设第k次两车相距m 小鸟在甲车处
飞到乙车时 两车相距
m-m/(20+30)*(15+20)=0.3m
再飞到甲车
0.3m-0.3m/(15+30)*(15+20)=1/15m
第k+1次往返两车距离为m/15
显然若m>0 第k+1次之后两车距离仍不为0
开始是两车相距100公里不为0 所以不论往返多少次 两车距离都不为0
本来解到这里,这个题目应该已经可以得出答案了。
但是很多朋友为了编程可实现,规定了一个距离精度,小于这个距离就认为两车相距,然后又递归或者迭代写了代码实现。但是程序员不是编码工,不是所有能实现的代码就是好的。不能只知道模拟,不考虑效率。
根据前面的证明 其实最后往返次数只是一个对数运算(注意求的是往返次数,而不是转身次数)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace bird
{
class Program
{
static void Main(string[] args)
{
double exactDistance = 0.000000001;
Console.WriteLine(Convert.ToInt32(Math.Ceiling(System.Math.Log(exactDistance / 1000, 1.0 / 15))));
}
}
}
最后关于时间无限细分的问题 其实类似很多年前就被提出并解决了:http://en.wikipedia.org/wiki/Zeno's_paradoxes
而且类似的计时制中,次数并不是一个悖论,距离才是。
所以这个问题作为面试题,是非常不错的题目,可以从不同的角度回答者的能力:
1.数学和逻辑思维基础:考察面试者是否了解类似的问题并且知道背景知识,能否独立想出解决方案
2.算法优化意识:考察面试者是否仅仅关注最表面的解决方法。二话不说直接写递归交差的程序员肯定不要
3.理解问题能力:考察面试者是否能正确理解问题,理解有偏差时,是否能主动沟通,弄清别人的真正意图。自己假设一堆条件的程序员肯定不要
4.编程语言基础:考察面试者是否能正确运用一门计算机语言。用==直接比较浮点数的程序员肯定不要