vlambda博客
学习文章列表

智力题(程序员面试6经典)

NO.1

 有20瓶药丸,其中19瓶装有1克/粒的药丸,余下一瓶装有1.1克/粒的药丸。给你一台称重精准的天平,怎么找出比较重的那瓶药丸?天平只能用一次。

解法

有时候,严格的限制条件有可能反倒是解题的线索。在这个问题中,限制条件是天平只能用一次。

因为天平只能用一次,我们也得以知道一个有趣的事实:一次必须同时称很多药丸,其实更准确地说,是必须从19瓶拿出药丸进行称重。否则,如果跳过两瓶或更多瓶药丸,又该如何区分没称过的那几瓶呢?别忘了,天平只能用一次。

那么,该怎么称重取自多个药瓶的药丸,并确定哪一瓶装有比较重的药丸?假设只有两瓶药丸,其中一瓶的药丸比较重。每瓶取出一粒药丸,称得重量为2.1克,但无从知道这多出来的0.1克来自哪一瓶。我们必须设法区分这些药瓶。

如果从药瓶#1取出一粒药丸,从药瓶#2取出两粒药丸,那么,称得重量为多少呢?结果要看情况而定。如果药瓶#1的药丸较重,则称得重量为3.1克。如果药瓶#2的药丸较重,则称得重量为3.2克。这就是这个问题的解题窍门。

称一堆药丸时,我们会有个“预期”重量。而借由预期重量和实测重量之间的差别,就能得出哪一瓶药丸比较重,前提是从每个药瓶取出不同数量的药丸。

将之前两瓶药丸的解法加以推广,就能得到完整解法:从药瓶#1取出一粒药丸,从药瓶#2取出两粒,从药瓶#3取出三粒,依此类推。如果每粒药丸均重1克,则称得总重量为210克(1 + 2 + … + 20 = 20 * 21 / 2 = 210),“多出来的”重量必定来自每粒多0.1克的药丸。

药瓶的编号可由算式(weight - 210 grams) / 0.1 grams得出。因此,若这堆药丸称得重量为211.3克,则药瓶#13装有较重的药丸。

NO.2

 有个8×8棋盘,其中对角的角落上,两个方格被切掉了。给定31块多米诺骨牌,一块骨牌恰好可以覆盖两个方格。用这31块骨牌能否盖住整个棋盘?请证明你的答案(提供范例,或证明为什么不可能)。

解法

乍一看,似乎是可以盖住的。棋盘大小为8×8,共有64个方格,但其中两个方格已被切掉,因此只剩62个方格。31块骨牌应该刚好能盖住整个棋盘,对吧?

尝试用骨牌盖住第1行,而第1行只有7个方格,因此有一块骨牌必须铺至第2行。而用骨牌盖住第2行时,我们又必须将一块骨牌铺至第3行。


要盖住每一行,总有一块骨牌必须铺至下一行。无论尝试多少次、多少种方法,我们都无法成功铺下所有骨牌。

其实,还有更简洁更严谨的证明说明为什么不可能。棋盘原本有32个黑格和32个白格。将对角角落上的两个方格(相同颜色)切掉,棋盘只剩下30个同色的方格和32个另一种颜色的方格。为方便论证起见,我们假定棋盘上剩下30个黑格和32个白格。

放在棋盘上的每块骨牌必定会盖住一个白格和一个黑格。因此,31块骨牌正好盖住31个白格和31个黑格。然而,这个棋盘只有30个黑格和32个白格,所以,31块骨牌盖不住整个棋盘。

智力题(程序员面试6经典)

NO.3

 有两个水壶,容量分别为5夸脱(美制:1夸脱=0.946升,英制:1夸脱=1.136升)和3夸脱,若水的供应不限量(但没有量杯),怎么用这两个水壶得到刚好4夸脱的水?注意,这两个水壶呈不规则形状,无法精准地装满“半壶”水。

解法

根据题意,我们只能使用这两个水壶,不妨随意把玩一番,把水倒来倒去,可以得到如下顺序组合:


注意,许多智力题其实都隐含数学或计算机科学的背景,这个问题也不例外。只要这两个水壶的容量互质(即两个数没有共同的质因子),我们就能找出一种倒水的顺序组合,量出1到2个水壶容量总和(含)之间的任意水量。

智力题(程序员面试6经典)

NO.4

 有个岛上住着一群人,有一天来了个游客,定了一条奇怪的规矩:所有蓝眼睛的人都必须尽快离开这个岛。每晚8点会有一个航班离岛。每个人都看得见别人眼睛的颜色,但不知道自己的(别人也不可以告知)。此外,他们不知道岛上到底有多少人是蓝眼睛的,只知道至少有一个人的眼睛是蓝色的。所有蓝眼睛的人要花几天才能离开这个岛?

解法

下面将采用简单构造法。假定这个岛上一共有n人,其中c人有蓝眼睛。由题目可知,c > 0。


情况c = 1:只有一人是蓝眼睛的

假设岛上所有人都是聪明的,蓝眼睛的人四处观察之后,发现没有人是蓝眼睛的。但他知道至少有一人是蓝眼睛的,于是就能推导出自己一定是蓝眼睛的。因此,他会搭乘当晚的飞机离开。

情况c = 2:只有两人是蓝眼睛的

两个蓝眼睛的人看到对方,并不确定c是1还是2,但是由上一种情况,他们知道,如果c = 1,那个蓝眼睛的人第一晚就会离岛。因此,发现另一个蓝眼睛的人仍在岛上,他一定能推断出c = 2,也就意味着他自己也是蓝眼睛的。于是,两个蓝眼睛的人都会在第二晚离岛。

情况c > 2:一般情况

逐步提高c时,我们可以看出上述逻辑仍旧适用。如果c = 3,那么,这三个人会立即意识到有2到3人是蓝眼睛的。如果有两人是蓝眼睛的,那么这两人会在第二晚离岛。因此,如果过了第二晚另外两人还在岛上,每个蓝眼睛的人都能推断出c = 3,因此这三人都有蓝眼睛。他们会在第三晚离岛。

不论c为什么值,都可以套用这个模式。所以,如果有c人是蓝眼睛的,则所有蓝眼睛的人要用c晚才能离岛,且都在同一晚离开。

NO.5

 有栋建筑物高100层。若从第N层或更高的楼层扔下来,鸡蛋就会破掉。若从第N层以下的楼层扔下来则不会破掉。给你2个鸡蛋,请找出N,并要求最差情况下扔鸡蛋的次数为最少。(这样问会不会好 最少试验多少次可以找出鸡蛋不会被摔碎的最高楼层?)解法 我们发现,无论怎么扔鸡蛋1(Egg 1),鸡蛋2(Egg 2)都必须在“破掉那一层”和下一个不会破掉的最高楼层之间,逐层扔下楼(从最低的到最高的)。例如,若鸡蛋1从5层和10层楼扔下没破掉,但从15层扔下时破掉了,那么,在最差情况下,鸡蛋2必须尝试从11、12、13和14层扔下楼。具体做法 首先,让我们试着从10层开始扔鸡蛋,然后是20层,等等。 如果鸡蛋1第一次扔下楼(10层)就破掉了,那么,最多需要扔10次。 如果鸡蛋1最后一次扔下楼(100层)才破掉,那么,最多要扔19次(10、20、…、90、100层,然后是91到99层)。这么做也挺不错,但我们只考虑了绝对最差情况。我们应该进行“负载均衡”,让这两种情况下扔鸡蛋的次数更均匀。我们的目标是设计一种扔鸡蛋的方法,使得扔鸡蛋1时,不论是在第一次还是最后一次扔下楼才破掉,次数越稳定越好。(1) 完美负载均衡的方法应该是,扔鸡蛋1的次数加上扔鸡蛋2的次数,不论什么时候都一样,不管鸡蛋1是从哪层楼扔下时破掉的。(2) 若有这种扔法,每次鸡蛋1多扔一次,鸡蛋2就可以少扔一次。(3) 因此,每丢一次鸡蛋1,就应该减少鸡蛋2可能需要扔下楼的次数。例如,如果鸡蛋1先从20层往下扔(不破),然后从30层扔下楼(破),此时鸡蛋2可能就要扔9次(从21到29 一次次试)。若鸡蛋1再扔一次,我们必须让鸡蛋2扔下楼的次数降为8次。也就是说,我们必须让鸡蛋1从39层扔下楼。(4) 由此可知,鸡蛋1必须从X层开始往下扔,然后再往上增加X-1层……直至到达100层。(5) 求解方程式X + (X-1) + (X-2) + … + 1 = 100,得到X (X + 1) / 2 = 100 → X = 14。(直接设要X次,假如X 和X-1这两次了

则再加X-2 总共还是X次, 次数总为X)我们先从14层开始,然后是27层,接着是39层,依此类推,最差情况下鸡蛋要扔14次。正如解决其他许多最大化/最小化的问题一样,这类问题的关键在于“平衡最差情况”。

NO.6  

走廊上有100个关上的储物柜。有个人先是将100个柜子全都打开。接着,每数两个柜子关上一个。然后,在第三轮时,再每隔两个就切换第三个柜子的开关状态(也就是将关上的柜子打开,将打开的关上)。照此规律反复操作100次,在第i轮,这个人会每数i个就切换第i个柜子的状态。当第100轮经过走廊时,只切换第100个柜子的开关状态,此时有几个柜子是开着的?解法 要解决这个问题,我们必须弄清楚所谓切换储物柜开关状态是什么意思。这有助于我们推断最终哪些柜子是开着的。1. 问题:柜子会在哪几轮切换状态(开或关)?柜子n会在n的每个因子(包括1和n本身)对应的那一轮切换状态。也就是说,柜子15会在第1、3、5和15轮开或关一次。(i=1开,3关,5开,15关。因子个数:偶数关,奇数开)2. 问题:柜子什么时候还是开着的?如果因子个数(记作x)为奇数,则这个柜子是开着的。你可以把一对因子比作开和关,若还剩一个因子,则柜子就是开着的。3. 问题:x什么时候为奇数?若n为完全平方数,则x的值为奇数。理由如下:将n的两个互补因子配对。例如,如n为36,则因子配对情况为:(1, 36)、(2, 18)、(3, 12)、(4, 9)、(6, 6)。注意,(6, 6)其实只有一个因子,因此n的因子个数为奇数。4. 问题:有多少个完全平方数?一共有10个完全平方数,你可以数一数(1、4、9、16、25、36、49、64、81、100),或者,直接列出1到10的平方:11, 22, 33, …, 1010 因此,最后共有10个柜子是开着的。