给你一个点数组 points 和一个表示角度的整数 a n g l e angle angle ,你的位置是 l o c a t i o n location location ,其中 l o c a t i o n = [ p o s x , p o s y ] location = [posx, posy] location=[posx,posy] 且 p o i n t s [ i ] = [ x i , y i ] points[i] = [xi, yi] points[i]=[xi,yi] 都表示 X − Y X-Y X−Y 平面上的整数坐标。
最开始,你面向东方进行观测。你 不能 进行移动改变位置,但可以通过 自转 调整观测角度。换句话说, p o s x posx posx 和 p o s y posy posy 不能改变。你的视野范围的角度用 a n g l e angle angle 表示, 这决定了你观测任意方向时可以多宽。设 d d d 为你逆时针自转旋转的度数,那么你的视野就是角度范围 [ d − a n g l e / 2 , d + a n g l e / 2 ] [d - angle/2, d + angle/2] [d−angle/2,d+angle/2] 所指示的那片区域。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-number-of-visible-points
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
- 用数学可以计算每个点相对于原点的一个角度, 当然光两个点是算不出来的, 我们可以预处理把观测点放到原点, 然后计算相对于 x x x轴的一个偏转角度。 然后, 我们就可以得到一个角度序列,排完序后,用滑动窗口就可以得到大部分得解。
- 处理一些特殊点。主要是分三个部分, 第一种是和原点重合得点, 直接放进去算的话,会出现除0的错误,单独统计就行了。 第二种情况是用三角函数计算的时候,+180 和 -180的角度是重合的,对于负数加上360就可以了。 第三种是, 我们用滑窗的算法去从角度最小的点作为起始点,但是这不是最优的,相当于是一个循环列表, 这种情况,只要复制一份加到后面去就可以了, A = A + A A = A + A A=A+A, 这题的话需要给后面扩展的角度序列加上360。
class Solution:
def visiblePoints(self, points: List[List[int]], angle: int, location: List[int]) -> int:
# location => (0, 0)
points = list(map(lambda P: (P[0] - location[0], P[1] - location[1]), points))
n = len(points)
points = [[x, y] for x, y in points if not (x == 0 and y == 0)]
cnt = n - len(points)
def f(P):
ret = math.atan2(P[1], P[0]) * 180 / math.pi
return 360 + ret if ret < 0 else ret
theta = sorted(list(map(f, points)))
theta += [x + 360 for x in theta]
m = len(theta)
L, R = 0, 0
ret = 0
while R < m:
if theta[R] - theta[L] <= angle:
#if R - L + 1 > ret: print(theta[L:R+1])
ret = max(ret, R - L + 1)
R += 1
else:
L += 1
return ret + cnt