螺旋队列

26 篇文章 0 订阅

螺旋队列的样子如下图:


两大规律:

1、螺旋规律

2、奇数(圈数,或X轴正坐标)平方规律(紫线)

 

问题描述:

 

设1的坐标是(0,0),x方向向右为正,y方向向下为正,例如,7的坐标为(-1,-1),2的坐标为(1,0)。编程实现输入任意一点坐标(x,y),输出所对应的数字!

 

 

问题解决:

从紫线突破。

从图中不难发现,每圈最大值max=(2*c+1)(2*c+1),c为由内往外的圈数,c>=0。如图每圈最大值分别是1、9、25、49、81........,算出每圈的max后,就分4条边分别计算每圈的其他值。通过坐标落在该圈4条边的哪条边上,按照不同的公式计算出具体坐标点的值。

以第3圈(max=49)为例,4条边划分如下图(以颜色区分):


 

这里先给出4条边上各坐标上的值与max的对应关系为:

上边:Utop = max+(x+y);

左边: Uleft= max+(3*x-y);

下边:Ubottom = max + (-x - 5*y);

右边:Uright = max+(-7*x+y);

 

那么这些关系是怎么得出来的呢?再看图中画上圈的数字(将其值表示为topBase,xxBase),我们称其为每条边的基准值:


 

在上边,y坐标不变,x坐标变化步长为1。令x=0,此时,topBase=max+y作为该边的基准值,其他值随x的变化而变化,得在该区域u=max+y+x;

同理,在左边,x坐标不变,y坐标变化步长为1。令y=0,此时,u=max+3*x作为该边的基准值,其他值随y的变化而变化,得在该区域u=vc+3*x-y;

同理得其他俩区域的表达式。不再赘述。

 观察这些基准值与max值之间关系,不难发现,这些基准值与max之间的差分别是1C(上边),3C(左边),5C(下边),7C(右边)(C表示当前圈数),在上边和下边,y坐标表示(或等于)圈数(即C=y),而在左边和右边,x坐标表示(或等于)圈数(即C=x)。因此前面提到的差值又可用坐标表示成1y,3x,5y,7x。因此就产生了各边基准值的计算公式:

topBase=max+y

leftBase=max+3x

bottomBase=max-5y

rightBase=max-7x

(注意坐标的符号,负数加,正数减,因为基准值肯定都比max要小)

下面得出每条边的值,首先考虑上边和下边,这2条边,在基准值的基础上,由x坐标控制增减,因此:

topValue=topBase+x=max+y+x(上边,随x赠而赠,因此是加x)

bottomValue=bottomBase-x=max-5y-x(下边,随x赠而减,因此是减x)

同理,左边和右边,则在基准值的基础上,由y坐标控制增减,因此:

leftValue=leftBase-y=max+3x-y(左边,随y赠而减,因此是减y)

rightValue=rightBase+y=max-7x+y(右边,随y赠而赠,因此是加y)


 程序实现

[java]  view plain copy
  1. /** 
  2.  * 打印螺旋数列 
  3.  *  
  4.  * @author nathan 
  5.  *  
  6.  */  
  7. public class SpiralSeq {  
  8.     public static void main(String[] args) {  
  9.         for (int y = -5; y <= 5; ++y) {  
  10.             for (int x = -5; x <= 5; ++x) {  
  11.                 System.out.printf("%5d", spiral(x, y));  
  12.             }  
  13.             System.out.println();  
  14.         }  
  15.     }  
  16.   
  17.     private static Object spiral(int x, int y) {  
  18.         int c = max(abs(x), abs(y));// 当前坐标所在圈  
  19.         int max = (c * 2 + 1) * (c * 2 + 1);// 当前圈上最大值  
  20.   
  21.         if (y == -c) { // 上边  
  22.             return max + (x + y);  
  23.         } else if (x == -c) {// 左边  
  24.             return max + (3 * x - y);  
  25.         } else if (y == c) {// 下边  
  26.             return max + (-x - 5 * y);  
  27.         } else {// 右边  
  28.             return max + (-7 * x + y);  
  29.         }  
  30.     }  
  31.   
  32.     private static int max(int n1, int n2) {  
  33.         return n1 > n2 ? n1 : n2;  
  34.     }  
  35.   
  36.     private static int abs(int x) {  
  37.         return x > 0 ? x : -x;  
  38.     }  
  39. }  

Output:
[java]  view plain copy
  1. 111  112  113  114  115  116  117  118  119  120  121  
  2. 110   73   74   75   76   77   78   79   80   81   82  
  3. 109   72   43   44   45   46   47   48   49   50   83  
  4. 108   71   42   21   22   23   24   25   26   51   84  
  5. 107   70   41   20    7    8    9   10   27   52   85  
  6. 106   69   40   19    6    1    2   11   28   53   86  
  7. 105   68   39   18    5    4    3   12   29   54   87  
  8. 104   67   38   17   16   15   14   13   30   55   88  
  9. 103   66   37   36   35   34   33   32   31   56   89  
  10. 102   65   64   63   62   61   60   59   58   57   90  
  11. 101  100   99   98   97   96   95   94   93   92   91  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值