由于网络问题,本页还有一些我自己画的说明图片没有贴上来,稍后会完善的。
另:对螺旋队列求解的举例说明和源代码放在下一篇文章《程序员面试宝典——螺旋队列解法解析2》中。
欢迎大家提出自己的见解,不明白的可以给我留言。
螺旋队列
面试例题:
看清以上数字排列的规律,设1点的坐标为(0, 0),x方向向右为正,y方向向下为正。
例如,7的坐标为(-1, -1),2的坐标为(0, 1),3的坐标为(1, 1)。
编程实现输入任意一点坐标(x, y),输出所对应的数字。
我的分析:
1.数字排列规律:以数字1为圆心,顺时针由里向外画圈,依次显示数字为1,2,3,4,5,6……,这就是所谓的螺旋队列。示意图如下:
2.依照题目要求建立坐标轴,示意图如下:
3.将螺旋队列从里到外画圈,依次编号为圈0,圈1,圈2……。
那么想要根据x、y坐标求取数字值v ,
首先要能根据x、y坐标确定当前所求数字在哪一圈。依据第2条特征,我们可知:x、y坐标绝对值的最大值即为当前所求数字所在的圈号,用 t 表示, t = max(|x| , |y|) 。
依据第1条特征可知,(2t+1)2 即为圈 t 的最大值,那么圈 t-1 的最大值为多少呢?对的,是(2t-1)2 。也就是说圈 t 所有数字的取值范围我们可以用这个半开半闭区间表示:( (2t-1)2 , (2t+1)2 ]。
那么圈 t 上的数字值v(x,y,t) = (2t-1)2 + 顺时针步长 。
下面的问题就是如何求顺时针步长,我们需要分情况讨论。分类的标准参照特征2,可分为以下4类。我们这里定义一个变量u,记录当前圈(即正方形)的边长。依据特征3,虽然圈 t 的每边有 2t+1 个数字,但是其边长为2t。u = 2t ,从前一圈的最大值顺时针数步长。
1) y = t 这一行
顺时针步长 = u + u/2 - x;
2) x = -t 这一列
顺时针步长 = 2u + u/2 - y;
3) y = -t 这一行
顺时针步长 = 3u + u/2 + x;
4) x = t 这一列
顺时针步长 = u/2 + y;
需要注意的是: x = t 这一列必须放在y = -t 这一行的后面求。这样做的原因是:坐标为(t, -t)的数字是当前圈t的最大值,这个最大值与y = -t 这一行的数字形成等差,单位步长为1,所以通过y = -t 这一行的公式来求是可取的;但是用x = t 这一列的公式来求就不对了。为了保证该坐标的数字用y = -t 的公式来求,必须在条件语句中将y = -t 放在x = t 之前。