LeetCode LCP 29. 乐团站位

LCP 29. 乐团站位

绕远路

为了我自己看起来舒服, 以下x``y坐标的定义与题目相反

彩笔如我, 看着题目题目描述需要环绕排序, 结果一不注意调起了自动脑补, 瞬间拆成分情况讨论...

然鹅这并不优雅, 姑且先记下来嘲笑过去的自己

为了坐标算起来方便, 位置起点为0, 每轮i拆解一次外层(半圈), 然后触发自动脑补机制逆时针旋转180°....

此时得到每轮起点位置与终点位置对应关系

i st add ed
0 0 2(n-1) 2(n-1)
1 2(n-1) + 1 2(n-2) 2(2n-1-2) + 1
2 2(2n-1-2) + 2 2(n-3) 2(3n-1-2-3) + 2
... ... ... ...
i 2(in- i*(i+1)/2) + i 2(n-1-i) 2((i+1)n - (i+2)(i+1)/2) + i
... ... ... ...
i i(2n-i) ... i(2n-i-2) + 2n-2

已知每段长度, 为方求(y, x)具体位置, 则需利用每段的起点/终点计算。因为每次只拆解半圈, 所以计算位置时只会发生横纵其中一个坐标的变动。(你这大脑是有多懒?

接下来则列出每轮拆解的起点/终点, [st(y,x), ed(y,x)]

i st(y,x) ed(y,x)
0 (0, 0) (n-1, n-1)
1 (n-1, n-2) (1, 0)
2 (1, 1) (n-2, n-2)
3 (n-2, n-3) (3, 2)
... ... ...
i (i/2, i/2) (n-1 - i/2, n-1 - i/2)
i (n-1 - (i-1)/2, n-2 - (i-1)/2) (i, (i+1)/2)
... ... ...
i (i/2, i/2) (n-1 - i/2, n-1 - i/2)
i (n - (i+1)/2, n - (i+3)/2) (i, (i+1)/2)

此时得到(y, x)i的对应关系, 但肉眼可见地出现了奇偶差异(更麻烦了, 喂!

于是根据不同区域, 上u, 右r, 下d, 左l, 进行分情况讨论...

区域 限制条件
u x=>y && x<n-y
r x=>y && x>=n-y
d x<y && x>=n-1-y
l x<y && x<n-y

最后, 根据条件按已列出的关系从下往上带入就能得到答案..._(ˊཀˋ」∠)_

Python3

class Solution:
    def orchestraLayout(self, num: int, xPos: int, yPos: int) -> int:
        x, y = yPos, xPos
        if x>=y and x<num-y:
            i = y*2
            st = i*(2*num-i)
            p = st + x-y
            return (p%9) + 1
        if x>=y and x>=num-y:
            i = (num-1 - x)*2
            ed = i*(2*num-i-2) + 2*num-2
            p = ed - (x-y)
            return (p%9) + 1
        if x<y and x>=num-1-y:
            i = 2*(num-y) - 1
            st = i*(2*num-i)
            p = st + y-1-x
            return (p%9) + 1
        if x<y and x<num-y:
            i = 2*x + 1
            ed = i*(2*num-i-2) + 2*num-2
            p = ed - (y - (x+1))
            return (p%9) + 1
        return -1

理论上

其实没必要每次拆半圈, 直接拆一整圈更方便。

于是乎, 将矩形分为2个部分, 其一是若干层完整的外环, 其二为(x, y)所在环的格子数。

外环 = 完整矩形 - 内部矩形

(x, y)的格子占用计算需要拆分为y>=xy<x两种情况, 这样x, y各自单调, 方便计算。(可作图观察到, 此处身略

为了方便描述, 定义a(x, y)所在位置与最外层的层数差, 可以简单认为a=min(x, y, n-1-x, n-1-y), 不过因为多了xy的限定条件可以一同拆分。

根据以上分情况讨论, 得到位置函数f(x, y)如下

[egin{aligned} f(x, y) &= egin{cases} n^2-(n-2a)^2 + (x+y-2a) &y>=x \ n^2 - [n-2(a+1)]^2 - (x+y-2a) &y<x end{cases} \ a &= egin{cases} min(x, n-1-y) &y>=x \ min(y, n-1-x) &y<x end{cases} end{aligned}]

此时已能得到答案, 不够由于强迫症发作, 故尝试整合表达式...

分解多项式后可以得到如下两个式子

[ f(x, y) = egin{cases} 4na - 4a^2 - 2a &+ (x+y) \ 4na - 4a^2 - 2a &- (x+y) + (4n-4a-4) end{cases} ]

增加两个变量b,c, 整合表达式

[egin{aligned} f(x, y) &= 4na - 4a^2 - 2a + b(x+y) + c(4n-4a-4) \ a &= egin{cases} min(x, n-1-y) &y>=x \ min(y, n-1-x) &y<x end{cases} \ b &= egin{cases} 1 &y>=x \ -1 &y<x \ end{cases} \ c &= egin{cases} 0 &y>=x \ 1 &y<x end{cases} end{aligned}]

再借助位运算完成1->0, -1->1的转换

得到最终表达式如下

[egin{aligned} f(x, y) &= 4na - 4a^2 - 2a + b(x+y) + (b gg 1&1)(4n-4a-4) \ a &= egin{cases} min(x, n-1-y) &y>=x \ min(y, n-1-x) &y<x end{cases} \ b &= egin{cases} 1 &y>=x \ -1 &y<x \ end{cases} end{aligned}]

Python3

class Solution:
    def orchestraLayout(self, num: int, xPos: int, yPos: int) -> int:
        a, b = (min(xPos, num-1-yPos), 1) if yPos >= xPos else (min(yPos, num-1-xPos), -1)
        return (4*num*a - 4*a*a - 2*a + b*(xPos+yPos) + (b>>1&1)*4*(num-a-1))%9 + 1
原文地址:https://www.cnblogs.com/Simon-X/p/15488067.html