LCP 29. 乐团站位
某乐团的演出场地可视作 num * num 的二维矩阵 grid(左上角坐标为 [0,0]),每个位置站有一位成员。乐团共有 9 种乐器,乐器编号为 1~9,每位成员持有 1 个乐器。
为保证声乐混合效果,成员站位规则为:自 grid 左上角开始顺时针螺旋形向内循环以 1,2,...,9 循环重复排列。例如当 num = 5 时,站位如图所示
请返回位于场地坐标 [Xpos,Ypos] 的成员所持乐器编号。
示例 1:
输入:num = 3, Xpos = 0, Ypos = 2
输出:3
解释:
示例 2:
输入:num = 4, Xpos = 1, Ypos = 2
输出:5
解释:
提示:
1 <= num <= 10^9
0 <= Xpos, Ypos < num
题解
暴力遍历
根据题意,我们可以从左上角开始遍历数组,围绕四个边每走一步将数字+1,当走到坐标点的时候,就可以得到答案。
注意:根据提议,xpos实际上是纵坐标!!!xpos是横坐标!!!
代码如下:
class Solution {
public:
int orchestraLayout(int num, int xPos, int yPos)
{
std::swap(xPos, yPos);
int left_x = 0;
int left_y = 0;
int right_x = num - 1;
int right_y = num - 1;
int value = 0;
int mod = 10;
while (left_x <= right_x && left_y <= right_y)
{
// 在左上角往右走
for (int i = left_x; i <= right_x; ++i)
{
value = (value == 9) ? 1: value + 1;
if (xPos == i && left_y == yPos)
{
return value;
}
}
// 在右上角往下走
for (int i = left_y + 1; i <= right_y; ++i)
{
value = (value == 9) ? 1: value + 1;
if (xPos == right_x && i == yPos)
{
return value;
}
}
// 在右下角往左走
for (int i = right_x - 1; i >= left_x; --i)
{
value = (value == 9) ? 1: value + 1;
if (xPos == i && right_y == yPos)
{
return value;
}
}
// 在左下角往上走
for (int i = right_y - 1; i >= left_y + 1; --i)
{
value = (value == 9) ? 1: value + 1;
if (xPos == left_x && i == yPos)
{
return value;
}
}
// 更新左上角、右下角的左边
left_x++;
left_y++;
right_y--;
right_x--;
}
return 0;
}
};
这个解法虽然简单易懂,但是超时了。实际上我们可以根据输入坐标判断该点在第几层,然后计算外面所有层的格子的个数得到本层开始时的值,然后再遍历四个方向。
通过坐标判断所在的层
思路:
- 根据给定的xpos和ypos确定所在的层level
- 计算level外的所有层的格子数目block_count
- 从level层的左上角开始遍历直到走到xpos和ypos,对结果取模
注意:
- level和block_count要使用long,或者显示的写成int64_t,否则会出现烦人的int溢出问题
- 返回的时候,如果对block_count的结果为0,则应该返回9
代码如下:
int orchestraLayout2(int n, int xPos, int yPos)
{
long level = std::min(std::min(n - xPos - 1, xPos), std::min(n - yPos - 1, yPos));
long block_count = (n * level - level * level) * 4 % 9;
std::swap(xPos, yPos);
int left_x = level;
int left_y = level;
int right_x = n - 1 - level;
int right_y = n - 1 - level;
int level_count = right_x - left_x;
if (yPos == left_y)
{
block_count = block_count + (xPos - left_x + 1);
}
else if (xPos == right_x)
{
block_count = block_count + level_count + (yPos - left_y + 1);
}
else if (yPos == right_y)
{
block_count = block_count + level_count * 2 + (right_x - xPos + 1);
}
else
{
block_count = block_count + level_count * 3 + (right_y - yPos + 1);
}
int value = block_count % 9 == 0 ? 9 : block_count % 9;
return value;
}