墙上的门
你面前是一堵朝两个方向无限延伸的墙。墙上有一扇门,但你不知道离你有多远,也不知道门位于哪个方向。你只有走到这扇门前才能看到它。假设从当前位置走到门前要走n步(事先并不知道n的大小),请设计一个算法,使你最多走O(n)步就能遇到门。([Par95])
解法:
首先,以当前位置为原点,门距离原点有n步(n未知),而且门位于哪个方向也不知道,所以不能只朝一个方向去找,万一选错方向就永远找不到门了。只能像钟摆一样以原点为中心来回找。也不能每多走一步就往另一个方向走,因为这样找到门时已经走了2*(1+2+3+...+n)步,即n*(n+1)步,对应于O(n^2)复杂度,不满足题目要求。
考虑 i 从0开始,先从原点出发向右走2^i步,返回原点,再向左走2^i步,再返回原点,接着向右走2^(i+1)步,返回原点,再向左走同样的2^(i+1)步...直到在途中找到门为止。由于门到原点的距离为n步,我们能找到一个整数k,使得2^(k-1) < n <= 2^k. 这样在找到门之前,你最多走了4*(2^0 + 2^1 + ... + 2^(k-1)) + 3*2^k 步,即4 * (2^k - 1) + 3 * 2^k < 7 * 2^k = 14 * 2^(k - 1) < 14 * n。这样就保证最多走O(n)步就能遇到门。