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>=x
与y<x
两种情况, 这样x
, y
各自单调, 方便计算。(可作图观察到, 此处身略
为了方便描述, 定义a
为(x, y)
所在位置与最外层的层数差, 可以简单认为a=min(x, y, n-1-x, n-1-y)
, 不过因为多了xy的限定条件可以一同拆分。
根据以上分情况讨论, 得到位置函数f(x, y)
如下
此时已能得到答案, 不够由于强迫症发作, 故尝试整合表达式...
分解多项式后可以得到如下两个式子
增加两个变量b
,c
, 整合表达式
再借助位运算完成1->0
, -1->1
的转换
得到最终表达式如下
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