摘要

本文主要讲解三种螺旋队列的实现方式和打印输出:

  • 从中心往外端顺时针旋转,记为『外螺旋队列』
  • 从左顶点开始,绕剩下的最大圈顺时针往内旋转,记为『内螺旋队列』
  • 从左顶点开始,之字形旋转(只能同行同列地移动),记为『 』螺旋队列』
  • 从左顶点开始,之字形旋转(只能沿-45°斜线移动),记为 『/ 螺旋队列 』

前三个螺旋队列图示如下:

1. 外螺旋队列

通过几个标记位,来确定其他值的大小,

由这两个值再来确定其他值,首先,我们可以确定这个值的大致范围: maxAbs=max{ fabs(r),fabs(c)},这样这个值就在 (2maxAbs-1)2~(2maxAbs+1)2的范围。接下来,我们从东南西北四个方向分析具体的值:

令$N=maxAbs$, 标志位上平方数元素的表示为:

\begin{gather}
f(-k,k) = (2k+1)^2 , \qquad k=0,1,2...\\
f(k,-(k-1)) = (2k)^2, \qquad k=1,2...
\end{gather}

  • 北:$f(r,c)=f(-N,N)-(N-c), \qquad r=-N,r<c$
  • 东:$f(r,c)=f(-(N-1),(N-1))+(r+(N-1))+1, \qquad c=N,r>-c$
  • 南:$f(r,c)=f(N,-(N-1))-(c+(N-1)), \qquad r=N,r>c$
  • 西:$f(r,c)=f(N,-(N-1))+(N-r)+1, \qquad c=-N,r<-c$
int rotQueue1(int r,int c)
{
if(r>0 && r+c==1)
return (2*r)*(2*r);
if(r<=0 && r+c==0)
return (2*c+1)*(2*c+1);
int N=fabs(r)>fabs(c)?fabs(r):fabs(c);
if( r==-N && r<c)
return rotQueue1(-N,N)-(N-c);
else if( c==N && r>-c)
return rotQueue1(-(N-1),(N-1))+(r+(N-1))+1;
else if( r==N && r>c )
return rotQueue1(N,-(N-1))-(c+(N-1));
else if( c==-N && r<-c)
return rotQueue1(N,-(N-1))+(N-r)+1;
}

2. 内螺旋队列

可以通过迭代建立数组,外圈循环从 i←0 to n/2,表示从外到内,循环圈子慢慢缩小,内圈循环从按照北东南西的顺序递增地建立数组。

int **rotQueue2(int r,int c)
{
int **a=malloc2D(r,c);
int m=1;
for(int i=0; i<r/2; i++)
{
for(int j=i;j<c-1-i;j++)
a[i][j] = m++;
for(int j=i;j<r-1-i;j++)
a[j][c-1-i] = m++;
for(int j=c-1-i;j>i;j--)
a[r-1-i][j] = m++;
for(int j=r-1-i;j>i;j--)
a[j][i] = m++;
}
if(r%2==1&&c%2==1)
a[r/2][c/2]=m;
return a;
}

3. 』螺旋队列

有两个方法确定数组:

  1. 可用标志位——平方数的加减得到,行列标从1开始的话, a(2k,1)=(2k)2 , a(1,2k-1)=(2k-1)2 类似于rotQueue1
  2. 类似于内螺旋队列,整体迭代赋值建立数组,下面用第二种。
int **rotQueue3(int N)
{
int **a=malloc2D(N,N);
int m=1;
a[0][0]=m++;
for(int i=1;i<N; ++i ){
if(i%2==1){
for(int j=0;j<=i;++j)// j为行
a[j][i]=m++;
for(int j=i-1;j>=0;--j)// j为列
a[i][j]=m++;
}
else{
for(int j=0;j<=i;++j)// j为列
a[i][j]=m++;
for(int j=i-1;j>=0;--j)// j为行
a[j][i]=m++;
}
}
return a;
}

4. / 螺旋队列 (zigzag数组)

可以将这个数组看成一个上三角形和一个倒三角形的组合。分成两部分赋值即可。(分析略去)。

5. 输出

最后,给出动态分配二维数组和打印程序,主程序与最后的结果。

int** malloc2D(int r,int c)
{
int **pt2D =(int**) malloc( r*sizeof(int*) );
for(int i=0; i< r;i++){
pt2D[i] = (int*)malloc( c*sizeof(int) );
for(int j=0;j<c;j++)
pt2D[i][j]=0;
}
return pt2D;
} void printRotQueue(int**a,int r,int c)
{
for(int i=0; i<r;i++){
for(int j=0;j<c;j++){
printf("%3d ",a[i][j]);
}
printf("\n");
}
} int main()
{
int r=5,c=5;
printf("rotQueue1(%d,%d):\n",r,r);
for(int i= -r/2; i<=r/2 ; ++i ){
for(int j= -r/2;j<=r/2;++j){
printf("%3d ",rotQueue1(i,j) );
}
printf("\n");
} int** a2=rotQueue2(r,c);
printf("\nrotQueue2(%d,%d):\n",r,c);
printRotQueue(a2,r,c);
printf("\nrotQueue3(%d,%d):\n",r,r);
int** a3=rotQueue3(r);
printRotQueue(a3,r,r);
return 0;
}

      

[interview]螺旋队列问题的更多相关文章

  1. 螺旋队列和hiho1525逃离迷宫3

    我是真调不出错误了! hiho1525逃离迷宫3 #include <stdio.h> #include <stdlib.h> #include <math.h> ...

  2. 螺旋队列(p98)

    先判断这个坐标代表的数位于哪一层,然后依据该层最大的数去计算这个坐标所代表的数. #include"iostream" #include"stdio.h" #i ...

  3. 语言总结—C/C++

    参考<程序员面试宝典> 1. 基本概念 1.1 赋值语句 例1. 按位与操作,例如:a=3,b=3,a&b值等于 0011 & 0011 结果还是0011,那么值还是3: ...

  4. 20140331 HOG代码调试 Boost库安装

    1.CUDAHOG代码调试 错误1: 错误提示:(main.obj : error LNK2019: 无法解析的外部符号 "public: __thiscall cudaHOG::cudaH ...

  5. 《Cracking the Coding Interview》——第3章:栈和队列——题目7

    2014-03-19 03:20 题目:实现一个包含阿猫阿狗的先入先出队列,我要猫就给我一只来的最早的猫,要狗就给我一只来的最早的狗,随便要就给我一只来的最早的宠物.建议用链表实现. 解法:单链表可以 ...

  6. 《Cracking the Coding Interview》——第3章:栈和队列——题目5

    2014-03-18 05:33 题目:用两个栈来实现一个队列. 解法:栈是反的,队列是正的,反了再反就正过来了.所以,请看代码.操作中时间复杂度有O(1)的,有O(n)的,但均摊下来时间符合O(1) ...

  7. 《Cracking the Coding Interview》——第3章:栈和队列——题目6

    2014-03-19 03:01 题目:给定一个栈,设计一个算法,在只使用栈操作的情况下将其排序.你可以额外用一个栈.排序完成后,最大元素在栈顶. 解法:我在草稿纸上试了试{1,4,2,3}之类的小例 ...

  8. 《Cracking the Coding Interview》——第3章:栈和队列——题目4

    2014-03-18 05:28 题目:你肯定听过汉诺威塔的故事:三个柱子和N个从小到大的盘子.既然每次你只能移动放在顶上的盘子,这不就是栈操作吗?所以,请用三个栈来模拟N级汉诺威塔的玩法.放心,N不 ...

  9. 《Cracking the Coding Interview》——第3章:栈和队列——题目3

    2014-03-18 05:17 题目:设计一个栈,这个栈实际上由一列子栈组成.每当一个子栈的大小达到n,就新产生下一个子栈.整个栈群对外看起来就像普通栈一样,支持取顶top().压入push().弹 ...

随机推荐

  1. [BZOJ4010]菜肴制作

    Description 知名美食家小 A被邀请至ATM 大酒店,为其品评菜肴. ATM 酒店为小 A 准备了 N 道菜肴,酒店按照为菜肴预估的质量从高到低给予 1到N的顺序编号,预估质量最高的菜肴编号 ...

  2. C#实现日历样式的下拉式计算器

    C#实现日历样式的下拉式计算器 原文地址:http://developer.51cto.com/art/201508/487486.htm 如果我们正在做一个类似于库存控制和计费系统的项目,有些部分可 ...

  3. js 苹果手机 keyup 事件不生效的问题

    $(document).on('keyup','input[name="txtInp"]',function(){}) 改 $(document).on('input proper ...

  4. geoserver源码学习与扩展——增加服务接口

    参看:http://www.cnblogs.com/sillyemperor/archive/2011/01/11/1929420.html 上文写的很详细了.

  5. geoserver源码学习与扩展——restAPI访问

    产生这篇文章的想法是在前端通过js调用restAPI时,总是不成功,发送ajax请求时还总是出现类似跨域的问题,后来查找才发现,默认情况下restAPI的访问都需要管理员权限,而通过ajax请求传输用 ...

  6. location的部分属性

    http://www.w3school.com.cn/jsref/dom_obj_location.asp location.host 可以设置或返回主机名和当前url的端口    www.w3sch ...

  7. C# 一些常用的字符串扩展方法

    以下可能是常用的.net扩展方法,记录下 EString.cs文件 /// <summary> /// 扩展字符串类 /// </summary> public static ...

  8. keepalived与nginx安装

    目的: 当用户请求访问时,会通过nginx来访问web服务应用,因此我们必须要保证nginx的高可用,要保证nginx的高可用,我们需要通过keepalived来监控nginx,并对外提供1个虚拟的v ...

  9. js实现类名的添加与移除

    方法1:使用className属性: 方法2:使用classList API: //用于匹配类名存在与否 function reg(name){ return new RegExp('(^|\\s)' ...

  10. js打乱数组的实战应用

    文章首发于: https://www.xiabingbao.com/post/javascript/js-random-array.html 在js中,能把数组随机打乱的方法有很多,每个方法都有自己的 ...