问题:
在一个坐标轴上, 给定两个点,一个起点,一个终点,起点有一个方块,方块可以左右移动,但是移动的长度只能是平方数长(1,4,9,16....) , 同时坐标轴上还有洞,移动的过程中不能停在洞的位置上,不然会掉下去,问由起点到终点 至少需要多少次移动,不能到达返回-1
解决方案:
记n为起始点与终点之间的距离, 在没有洞的情况下有
若 n = 2*k + 1 (k为整数), 则有 n = (k+1)^2 - k^2
若 n = 1 + ( 2*k + 1 ), 有 n = 1 + (k+1)^2 - k^2
因此,没有洞的情况下,总是在三步之内达到终点
在有洞的情况下可以这样分析(不防假设起始点在终点的左边)
记从起始点右侧 s 距离开始没有洞(假设洞的个数是有限个,暂时没考虑洞是无限个的情况)
则有:
若 n 奇数,可以找到一个偶数 k1 = (s&1)?(s+1):s , 和 k2 使得
(k2+1)^2 - k2^2 = k1^2 - 1 , 因此 n 为奇数的情况下总可以走三步到达终点
若 n 为偶数, 同样可以找到奇数 k1 = (s&1)?s:(s+1),以及类似上面的 k2 使得在三步之内到达终点
因此剩下的问题的我们能否在两步到达终点(一步能达到的情况很好判断)
两步能到达只有如下四种情况
(1) k1^2 + k2^2 = n
(2) k2^2 + k1^2 = n
(2) k1^2 - k2^2 = n
(3) -k2^2 + k1^2 = n
找到所有 k1 k2 看能否不停留在洞的位置到达终点即可
因此这个问题,变成了找满足上述条件(实际上可以归纳为两个)之一的k1, k2
对于(1)这种情况,能在 O(sqrt(n))时间复杂度找到所有满足条件的 k1, k2(对k1从1到sqrt(n)依次判断)
对于(3)这种情况,可以设 k1 = k3 + t (t>0)
则有 k1^2 - k2^2 = t^2 + 2*k3*t = n , 也可以对 t 从 1 到 sqrt(n) 进行依次判断
综上所述这个问题能在O(sqrt(n))时间复杂度完成
关于求 k^2算法
s = 1;
nextpow = 1;
while(s<k){
nextpow += 1 + s<<1;
++s;
}