题目描述
某乐团的演出场地可视作 num * num 的二维矩阵 grid(左上角坐标为 [0,0]),每个位置站有一位成员。乐团共有 9 种乐器,乐器编号为 1~9,每位成员持有 1 个乐器。
为保证声乐混合效果,成员站位规则为:自 grid 左上角开始顺时针螺旋形向内循环以 1,2,…,9 循环重复排列。例如当 num = 5 时,站位如图所示
请返回位于场地坐标 [Xpos,Ypos] 的成员所持乐器编号。
我的解法
class Solution {
public int orchestraLayout(int num, int xPos, int yPos) {
int[][] grids = new int[num][num];
int number=1;
int x_up=0,x_down=num-1,y_left=0,y_right=num-1;
while(y_right>=y_left&&x_up<=x_down){
//首先y向右添加
for(int i=y_left;i<=y_right;i++){
grids[x_up][i]=number++;
if(number>9){number%=9;}
}
x_up++;
//x向下添加
for(int j=x_up;j<=x_down;j++){
grids[j][y_right]=number++;
if(number>9){number%=9;}
}
y_right--;
//y向左添加
for(int m=y_right;m>=y_left;m--){
grids[x_down][m]=number++;
if(number>9){number%=9;}
}
x_down--;
//x向上添加
for(int n=x_down;n>=x_up;n--){
grids[n][y_left]=number++;
if(number>9){number%=9;}
}
y_left++;
}
return grids[xPos][yPos];
}
}
官方解法
思路:
1.获取所求点在第几层
2.前第0,1…k层的数量和 与 所求点相对第k层左上角元素(第k层的入口元素)的相对路径做+或-运算,求得所求点的绝对路径(从起始点到所求点经过的长度)
记:k(0,1,2…⌈n/2⌉ (往上取整))
C(k)=第k层的方块数目,如图C(0)=16,C(1)=8,C(2)=1;
T(k)=第k层以外(不包括第k层)的方块 数目,如图T(0)=0,T(1)=C(0)=16,T(2)=C(0)+C(1)=16+8=24,T(3)=16+8+1=25;
但是具体怎么计算呢 可以用补集的思想
T(k)=nn-(n-2k)(n-2k)=4k(n-k)
但是怎么求(i,j)点所在层 已经遍历过的数目呢 。(即下图深蓝色的路径长度)
1.求所在的层数k
k=min(x,n-1-x,y,n-1-y)(后续由于要分类讨论,k的求取可以直接通过其中某两个值求最小值即可); 即看该点距离哪个边界更近,所求的最小值就是第几层,如图 k=min(2,2,3,1),即处于第一层。那么我们也就知道了该层以外的橙色数目T(k)=T(1)=16。
2.求所求点(x,y)相对该层左上角点的相对路径长度
2.1 对于x<=y,我们可以知道dl=(x-k)+(y-k)+1
故 绝对路径长度为 T(k)+dl
2.2 但是对于x>y呢
如果我们采用相同的方法,就会导致对称的两个(i,j)与(j,i)相对路径相同。故才用另外一种方法,在计算层数k的时候 多计算一层内圈,再退dl-2个路径此时绝对路径长度为 T(k+1)-dl ,dl=(x-k)+(y-k)-1
(至于为何此处可直接-dl,可以看下图,下一层的入口点与上一层的入口点是右下和左上关系,按照螺旋顺序到(i,j)点的路径长度是相同的。)
最后, 就是把相应的路径长度len转化为1-9的数字即可,考虑到9%9=0,index=(len-1)%9+1。
当然此题也可拓展到mn型的矩阵,最后一圈应该是一条线。nn可以看作是m*n的特例,对于n为奇数的情况,一条线压缩成了一个点。
class Solution {
public int orchestraLayout(int num, int xPos, int yPos) {
long n=num,x=xPos,y=yPos;
long k=Math.min(x,Math.min(y,Math.min(n-x-1,n-y-1)));
if (x <= y) {
return (int)((4*k*(n-k)+1+(x-k)+(y-k)-1)%9+1);
}
return (int)((4*(k+1)*(n-k-1)+1-(x-k)-(y-k)-1)%9+1);
}
}
官方解法
我的解决方法中输出了整个表的数据,实际上他是个找规律的题目。
取余要考虑到9%9=0,所以要做一下改变。
找规律的过程会花很长时间,但是主要用到的思想还是补集。
在计算单圈个数的时候,是用外圈减去内圈
计算单圈偏移的时候,两种情况,一种是直接计算,一种是整圈算下来减去直接计算的结果再消除误差。很简单,但是如果没想到就会算得很麻烦还百思不得其解,我大概是脑子秀逗了,看了好久才看明白。