LeetCode——1610.可见点的最大数目

通过万岁!!!

  • 题目:就是给你一个点,然后给你一个角度(也就是视野的角度angle)。可以在这个点上转动,但不能移动。看看周围的点,最多多少个出现在你的视野中。点都是在平面直角坐标系上的,给出一个二维数组,数组中就是点的横坐标和纵坐标。
  • 思路:也就是说,我们的角度是angle,角有两条边我们转动起始边即可。可以想到一种类似滑动窗口,我们的窗口大小是固定的,然后看里面最多能出现多少个点。那我们以角度为单位,将目标点的角度计算出现。
  • 注意:这里题目中有几个比较坑。就是自己所占的点,也可能是目标点。
  • 技巧:
    • 首先是将角度计算出来,然后存到一个数组中,这里需要对这个数组进行排序的。
    • 其次,滑动窗口其实就是两个指针,我们left从0开始,然后right进行++,++的前提是指向的角度要小于我们的视野角,否则让left++。
    • 然后就是java中的,java的arctan公式,也就是atan2()计算出来的结果不是0到360,而是0到2PI。而给出的angle是角度0到360的形式。
    • 并且,因为我们的角度是0到2PI,所以我们还需要考虑当left转动一圈后快要到达2PI的时候,因为到达2PI就是一圈了,我们就可以停止了。这时候我们可以对数组进行补全。也就是说,我们计算出来的角度小于angle的时候,需要将这些点+2PI。当然,可以直接将数组复制一分,添加到后面,但是空间复杂度会略高。

伪代码

定义一个自己所在的点loc
定义目标点角度的数组angles
遍历目标点,计算点的角度
    如果是自己所在点,loc++,并且continue。
    计算角度值目标点与所占点之间的角度。并添加到angles中。
angles数组进行排序
遍历angles数组,将小于angle的元素+2PI后添加到数组中。(这里只能用fori的循环遍历,并且条件是小于angles.size(),而这个值必须要提前存储,否则添加元素数组就变了,这样会报并发错误)
定义max,用来存储最大的点数。
双指针遍历数组,条件是right要小于angles的长度
    如果,right指向的角度-left指向的角度小于视野角,那么right++
    否则,取right-left和max的最大值。并且left++
return loc+max;

java代码

class Solution {
    public int visiblePoints(List<List<Integer>> points, int angle, List<Integer> location) {
        int loc = 0;// 自己所在点,也是可以检测到的
        ArrayList<Double> angles = new ArrayList(points.size());
        for (List<Integer> point : points) {
            if (point.get(0) == location.get(0) && point.get(1) == location.get(1)) {
                loc++;
                continue;
            }
            angles.add(Math.atan2(point.get(0) - location.get(0), point.get(1) - location.get(1)));// 角度,是PI的那种形式
        }
        Collections.sort(angles);
        // 使用双指针遍历angles数组,两个指针之间的距离不能超过angle,让慢指针需要到达360,因此需要将angles中角度小于angle的加上360
        double anglePI = angle * Math.PI / 180;// 将给定的角度转换为PI的形式
        int temp = angles.size();// 这里必须这样使用fori,不然会数组一直遍历不完
        for (int i = 0; i < temp; i++) {
            if (angles.get(i) < anglePI) angles.add(angles.get(i) + 2 * Math.PI);
            else break;
        }
        temp = 0;// 这个就是max
        int left = 0, right = 0;
        while (right < angles.size()) {
            if (angles.get(right) - angles.get(left) <= anglePI) {
                right++;
            } else {
                temp = temp > (right - left) ? temp : right - left;
                left++;
            }
        }
        return temp + loc;
    }
}
  • 总结:这个题技巧性比较强,我们必须要将二维的点,变成一维的角,然后使用滑动窗口。其实滑动窗口就是双指针。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值