螺旋队列算法分析

 

螺旋队列的样子如下图:


两大规律:

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)


 程序实现

/**
 * 打印螺旋数列
 * 
 * @author nathan
 * 
 */
public class SpiralSeq {
	public static void main(String[] args) {
		for (int y = -5; y <= 5; ++y) {
			for (int x = -5; x <= 5; ++x) {
				System.out.printf("%5d", spiral(x, y));
			}
			System.out.println();
		}
	}

	private static Object spiral(int x, int y) {
		int c = max(abs(x), abs(y));// 当前坐标所在圈
		int max = (c * 2 + 1) * (c * 2 + 1);// 当前圈上最大值

		if (y == -c) { // 上边
			return max + (x + y);
		} else if (x == -c) {// 左边
			return max + (3 * x - y);
		} else if (y == c) {// 下边
			return max + (-x - 5 * y);
		} else {// 右边
			return max + (-7 * x + y);
		}
	}

	private static int max(int n1, int n2) {
		return n1 > n2 ? n1 : n2;
	}

	private static int abs(int x) {
		return x > 0 ? x : -x;
	}
}

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


你可能感兴趣的:(常用算法收集,面试)