摘要

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

  • 从中心往外端顺时针旋转,记为『外螺旋队列』
  • 从左顶点开始,绕剩下的最大圈顺时针往内旋转,记为『内螺旋队列』
  • 从左顶点开始,之字形旋转(只能同行同列地移动),记为『 』螺旋队列』
  • 从左顶点开始,之字形旋转(只能沿-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. PHP设计模式(二):工厂方法模式

  2. TeeChart.Direct2D.dll的使用

    这个dll本身依赖于第三方的控件,SlimDX ,可以从 http://slimdx.org/ 下载.  .net4.0的版本区分x86和x64 帧数的概念 我们通常说帧数,简单地说,就是在1秒钟时间 ...

  3. 网络流learning

    上次学习网络流还是大一的下学期,之后就被从图论分出来交给队友了 然而吉林一战,队友在深圳读研而不能来,于是需要自己学习一下,争取在比赛前看完网络流建模汇总和一些总结,升华一下. 同时记录一下自己做过的 ...

  4. shell基本认识

    shell基本认识 bash # echo $BASH /bin/bash 第一个shell脚本first_shell.sh #!/bin/bash echo "Hello world!&q ...

  5. ORM框架greenDao 2 (用于了解旧版本的使用方法,目前最新版本为3.2.2,使用注释的方式来生成)

    摘要: Android中对SQLite数据库使用,是一件非常频繁的事情.现今,也有非常多的SQLite处理的开源框架,其中最著名的greenDao,它以占用资源少,处理效率高等特点,成为优秀的ORM框 ...

  6. angular之自定义 directive

    1,指令的创建至少需要一个带有@Directive装饰器修饰的控制器类.@Directive装饰器指定了一个选择器名称,用于指出与此指令相关联的属性的名字. 2,创建一个highlight.direc ...

  7. c语言的tcp和udp客户端和服务器

    都是最简单的用来记忆. this is my 的git地址:https://github.com/yanjinyun/cLanguageTcpUdp tcp最简单的服务器: int main(int ...

  8. 搞懂分布式技术12:分布式ID生成方案

    搞懂分布式技术12:分布式ID生成方案 ## 转自: 58沈剑 架构师之路 2017-06-25 一.需求缘起 几乎所有的业务系统,都有生成一个唯一记录标识的需求,例如: 消息标识:message-i ...

  9. 使用libimobiledevice + ifuse提取iOS沙盒文件

    简介 libimobiledevice:一个开源包,可以让Linux支持连接iPhone/iPod Touch等iOS设备. Git仓库: https://github.com/libimobiled ...

  10. 通过windows的超级终端连接华为交换机

    如果你的电脑没有带COM接口 可以找一个COM--->USB的转换器 我前面有介绍过这么安装COM转USB设备的驱动 2 先打开你电脑的设备管理器 看看你的com接口数字编号 这里看到的是COM ...