【leetcode-Python】-找数学规律-LCP 29. 乐团站位

题目链接

https://leetcode-cn.com/problems/SNJvJP/

题目描述

某乐团的演出场地可视作 num * num 的二维矩阵 grid(左上角坐标为 [0,0]),每个位置站有一位成员。乐团共有 9 种乐器,乐器编号为 1~9,每位成员持有 1 个乐器。

为保证声乐混合效果,成员站位规则为:自 grid 左上角开始顺时针螺旋形向内循环以 1,2,...,9 循环重复排列。例如当 num = 5 时,站位如图所示:

请返回位于场地坐标 [Xpos,Ypos] 的成员所持乐器编号。1<=num<=10^9,0<=xPos,yPos < num。

示例

输入:num = 4,xPos = 1,yPos = 2

输出:5

解题思路

对于这类找数学规律的问题,我们要在充分理解题意的基础上通过举来挖掘规律。如果我们知道某位置是生成螺旋矩阵时的第res个数(从1开始计),我们可以很容易得到某个位置的乐器编号:如果res%9==0,那么乐器编号为9;如果res%9!=0,那么乐器编号就是res%9。(需要做判断,不能直接返回res%9)

。比如num=4的螺旋矩阵为:

比如对于x=2,y=1的位置,计数为16,那么乐器编号为16%9 = 7。如果直接遍历螺旋矩阵来得到计数的话,对于10^9的数据规模,O(N)的时间复杂度会导致TLE。因此我们要找规律来得到当前位置的计数。我们能够很容易观察到,螺旋矩阵是一圈一圈绕进去的,我们可以直接根据给定的矩阵边长,和当前位置(xPos,yPos)得到计数结果:

1、首先要确定当前位置所在的层数(从0开始计)。容易发现,层数是当前位置距离上、下、左、右四个边界的最小值min(xPos,num-1-xPos,yPos,num-1-yPos)。当前位置和上边界的距离为xPos,和下边界的距离为num-1-xPos,和左边界的距离为yPos,和右边界的距离为num-1-yPos。比如对于num=4的螺旋矩阵中的(1,3)位置,该位置距离上边界的距离为1,距离下边界的距离为2,距离左边界的距离为3,距离右边界的距离为0。因此(1,3)位置在螺旋矩阵的第0层。记当前位置在螺旋矩阵的第k层。

2、确定当前位置所在层数后,我们要知道层数小于当前层(环绕当前层)的层中有多少个元素,因为这些元素一定都在当前位置的前面。在计数走到当前层的当前位置之前,环绕当前层的层一定已经被填满了。

得到环绕当前层的层中元素个数有两种方法:

(1)我们根据num=5的螺旋矩阵找规律:

第k层的边长为n-2k,由此也很容易能得出第k层的元素个数4*(n-2k-1)),第0层的元素个数为4*(n-1),第1层的元素个数4*(n-2-1),每层的元素个数构成公差为8的等差序列。因此如果当前位置在第k层,那么从第0层到第k-1层(共有k层)的元素总和为((4*(n-1) + 4*(n-2(k-1)-1))*(k))/2 = 4k(n-k)。

(2)让大正方形中元素个数减去当前层所在的小正方形中元素个数。大正方形中元素个数为n*n,小正方形的边长为(n-2k),因此结果为n*n-(n-2k)*(n-2k) = 4k(n-k)。

3、最后计算当前位置是生成当前层时的第几个值(从1开始计数),这要看当前位置在这一层上、下、左、右中的哪个位置,当前层所在小正方形的边长为size = n-2k,当前层(第k层)所构成的正方形的左上角坐标为(k,k),(k,k)是当前层中的第一个元素。我们令x = xPos-k,y = yPos-k,那么x,y分别是当前位置以(k,k)为坐标原点时的相对坐标。

(我们得到下面公式时要举个例子看是否正确,也可以通过例子倒推公式)

如果x==0,那么当前位置在第k层的上边界,当前位置是当前层的第y+1个值。

如果y==size-1,那么当前位置在第k层的右边界,当前位置是当前层的第size+x个值。

如果x==size-1,那么当前位置在第k层的下边界,当前位置是当前层的第2*(size-1)+size-y个值。

如果y==0,那么当前位置在第k层的左边界,当前位置是当前层的第3*(size-1)+size-x个值。

Python实现

class Solution:
    def orchestraLayout(self, num: int, xPos: int, yPos: int) -> int:
        res = 0
        k = min(xPos,yPos,num-1-xPos,num-1-yPos) #当前所在层数
        res += 4*k*(num-k) #环绕当前层的层中元素个数
        size = num-2*k #size为当前层边长
        x = xPos-k#相对坐标
        y = yPos-k #相对坐标
        if(x == 0): #在上边界
            res += (y+1)
        elif(y == size-1):#在右边界
            res += (size+x)
        elif(x == size -1): #在下边界
            res += 2*(size-1) +size-y
        else:#在左边界
            res += 3*(size-1) + size-x
        return 9 if res%9==0 else res%9

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值