LeetCode LCP 29. 乐团站位(数学 等差数列)

1. 题目

某乐团的演出场地可视作 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

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/SNJvJP
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2. 解题


从 (0, -1) 出发,发现 每个边走到尽头的步数规律 n, n-1, n-1, n-2, n-2 …

2.1 模拟超时

class Solution {
public:
    int orchestraLayout(int num, int xPos, int yPos) {
        long long tot = 1LL*num*num, ct = 0;
        long long x0 = 0, y0 = 0, x1 = 0 , y1 = -1, delta = num, i = 0;
        long long d, idx;
        while(ct < tot)
        {
            if(i%2 == 1)
                delta--;//奇数的时候,步长减少 1
            ct += delta; // 总的格数
            if(i%4==0) // 四个方向挪动的坐标
            {
                y1 += delta;
            }
            else if(i%4 == 1)
            {
                x1 += delta;
            }
            else if(i%4 == 2)
            {
                y1 -= delta;
            }
            else
            {
                x1 -= delta;
            }
            if(x0 == xPos && x1 == xPos && 
                ((yPos >= y0 && yPos <= y1) || (yPos >= y1 && yPos <= y0)))
            {	// 如果在前后端点之间,则找到位置
                d = abs(y1-yPos); // 计算偏差
                idx = ct-d; // 减去偏差格数
                break;
            }
            else if(y0 == yPos && y1 == yPos && 
                ((xPos >= x0 && xPos <= x1) || (xPos >= x1 && xPos <= x0)))
            {
                d = abs(x1-xPos);
                idx = ct-d;
                break;
            }
            x0 = x1;
            y0 = y1;
            i++;
        }
        return (idx%9==0) ? 9 : (idx%9);  // 返回序号
    }
};

2.2 优化通过

  • 先找出这个坐标处在第几层
  • 等差数列求和,所有外层的格子数目
  • 再利用上面的代码,遍历所在的一圈就可以找出答案
class Solution {
public:
    int orchestraLayout(int num, int x, int y) {
        int a = num-x, b = num-y;
        int layer = min(x+1,min(a, min(y+1, b)));//所在的圈
        layer--;// 外面有多少个完整的圈
        long long  ct = 4LL*layer*(num-layer), idx;
        // 每圈的边长 为 n, 则 格子数 为 4(n-1)
        // 第 layer 圈 的边长 n-2(layer-1)
        // 外部完全圈的格子总数:layer*4(n-1+n-2(layer-1)-1)/2
        // = 2*layer*(2n-1-2layer+2-1) = 4*layer(n-layer)
        int delta = num - 2*layer, i = 0;
        // (x,y)点 所在圈的 边长 delta 
        int x0 = layer,y0 = layer-1, x1 = layer, y1 = layer-1, d;
        // 起点坐标 x1, y1
        while(i < 4) { // 遍历 目标点所在的圈
            if(i%2 == 1)
                delta--;
            ct += delta;
            if(i%4==0)
            {
                y1 += delta;
            }
            else if(i%4 == 1)
            {
                x1 += delta;
            }
            else if(i%4 == 2)
            {
                y1 -= delta;
            }
            else
            {
                x1 -= delta;
            }
            if(x0 == x && x1 == x && 
                ((y >= y0 && y <= y1) || (y >= y1 && y <= y0)))
            {
                d = abs(y1-y);
                idx = ct-d;
                break;
            }
            else if(y0 == y && y1 == y && 
                ((x >= x0 && x <= x1) || (x >= x1 && x <= x0)))
            {
                d = abs(x1-x);
                idx = ct-d;
                break;
            }
            x0 = x1;
            y0 = y1;
            i++;
        }
        return (idx%9==0) ? 9 : (idx%9);
    }
};

0 ms 5.7 MB C++


我的CSDN博客地址 https://michael.blog.csdn.net/

长按或扫码关注我的公众号(Michael阿明),一起加油、一起学习进步!
Michael阿明

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: Age of Ai 设计师:meimeiellie 返回首页