[Leetcode] 1610. 可见点的最大数目

给你一个点数组 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 XY 平面上的整数坐标。

最开始,你面向东方进行观测。你 不能 进行移动改变位置,但可以通过 自转 调整观测角度。换句话说, 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] [dangle/2,d+angle/2] 所指示的那片区域。

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

思路

  1. 用数学可以计算每个点相对于原点的一个角度, 当然光两个点是算不出来的, 我们可以预处理把观测点放到原点, 然后计算相对于 x x x轴的一个偏转角度。 然后, 我们就可以得到一个角度序列,排完序后,用滑动窗口就可以得到大部分得解。
  2. 处理一些特殊点。主要是分三个部分, 第一种是和原点重合得点, 直接放进去算的话,会出现除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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值