外螺旋队列
上图即为外螺旋队列的样子,即向外螺旋伸展。
问题:设1的坐标是(0,0),x方向向右为正,y方向向下为正,例如,7的坐标为(-1,-1),2的坐标为(1,0)。编程实现输入任意一点坐标(x,y),输出所对应的数字!
思路:
从图中不难发现,每圈最大值max=(2*t+1)(2*t+1),即紫色方块中的值,t为由内往外的圈数,t>=0。如图每圈最大值分别是1、9、25、49、81........,算出每圈的max后,就分4条边分别计算每圈的其他值。通过坐标落在该圈4条边的哪条边上,按照不同的公式计算出具体坐标点的值。
从上图中可以看出,四个边框中间的值对于求值十分有帮助,并且这四个值也很容易求得:
1,上边框中点值: max - t
1,左边框中点值: max -3t
1,下边框中点值: max - 5t
1,上边框中点值: max - 7t
对于落在四个边框上的值可以用加减x或y直接求得:
int Spiral1(int x,int y)
{
int t = max(abs(x),abs(y));
int u = 2 * t;
int max = ( u + 1)*(u + 1);
int v;
if (x == -t) //左边框
v = max - 3 * t - y;
else if (y == -t) //上边框
v = max - t + x;
else if (y == t) //下边框
v = max - 5 * t - x;
else //右边框
v = max - 7 * t + y;
return v;
}
内螺旋队列
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
如上所示的即为内螺旋队列,即逐渐向内螺旋收缩。
具体的求解方式即控制x和y的左边逐渐从外圈向内圈收缩,首先从上边框向右伸展,然后从右边框向下伸展,然后从下边框从右往左伸展,再从左边框从下往上伸展。
代码:
int Spiral2(int **a,int n)
{
int m = 1,i,j;
for(i = 0; i < n/2; i++)
{
/* 上边框 */
for(j = 0; j < n - i; j++)
{
if(a[i][j] == 0)
a[i][j] = m++;
}
/* 右边框 */
for(j = i + 1;j < n - i; j++)
{
if(a[j][n-i-1] == 0)
a[j][n-i-1] = m++;
}
/* 下边框 */
for(j = n - i -1; j > i;j--)
{
if(a[n-i-1][j] == 0)
a[n-i-1][j] = m++;
}
/* 左边框 */
for(j = n - i -1;j > i; j--)
{
if(a[j][i] == 0)
a[j][i] = m++;
}
if(n & 0x1)
a[n>>1][n>>1] = m;
}
}
测试程序(注意C++申请动态二维数组的方式):
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
inline int max(int x,int y)
{
return x>y?x:y;
}
int Spiral1(int x,int y)
{
int t = max(abs(x),abs(y));
int u = 2 * t;
int max = ( u + 1)*(u + 1);
int v;
if (x == -t) //左边框
v = max - 3 * t - y;
else if (y == -t) //上边框
v = max - t + x;
else if (y == t) //下边框
v = max - 5 * t - x;
else //右边框
v = max - 7 * t + y;
return v;
}
int Spiral2(int **a,int n)
{
int m = 1,i,j;
for(i = 0; i < n/2; i++)
{
/* 上边框 */
for(j = 0; j < n - i; j++)
{
if(a[i][j] == 0)
a[i][j] = m++;
}
/* 右边框 */
for(j = i + 1;j < n - i; j++)
{
if(a[j][n-i-1] == 0)
a[j][n-i-1] = m++;
}
/* 下边框 */
for(j = n - i -1; j > i;j--)
{
if(a[n-i-1][j] == 0)
a[n-i-1][j] = m++;
}
/* 左边框 */
for(j = n - i -1;j > i; j--)
{
if(a[j][i] == 0)
a[j][i] = m++;
}
if(n & 0x1)
a[n>>1][n>>1] = m;
}
}
int main()
{
int x,y;
for(y = -4;y <= 4; y++){
for( x = -4; x <= 4; x++){
cout<<setw(5)<<Spiral1(x,y);
}
cout<<endl;
}
cout<<endl;
int **a = new int* [8];
for(int i = 0; i < 8; i++){
a[i] = new int[8];
memset(a[i],0,8*sizeof(int));
}
Spiral2(a,5);
for(y = 0;y < 5; y++){
for( x = 0; x < 5; x++){
cout<<setw(5)<<a[y][x];
}
cout<<endl;
}
for(int i = 0; i < 8; i++)
delete [] a[i];
delete [] a;
}
输出:
73 74 75 76 77 78 79 80 81
72 43 44 45 46 47 48 49 50
71 42 21 22 23 24 25 26 51
70 41 20 7 8 9 10 27 52
69 40 19 6 1 2 11 28 53
68 39 18 5 4 3 12 29 54
67 38 17 16 15 14 13 30 55
66 37 36 35 34 33 32 31 56
65 64 63 62 61 60 59 58 57
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
1,http://blog.youkuaiyun.com/yhmhappy2006/article/details/2934435
2,程序员面试宝典 第三版 P91