LeetCode破解之正方形检查

157 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第25天,点击查看活动详情

题目描述

给你一个在 X-Y 平面上的点构成的数据流。设计一个满足下述要求的算法:

  • 添加 一个在数据流中的新点到某个数据结构中。可以添加 重复 的点,并会视作不同的点进行处理。

  • 给你一个查询点,请你从数据结构中选出三个点,使这三个点和查询点一同构成一个 面积为正 的 轴对齐正方形 ,统计 满足该要求的方案数目。

轴对齐正方形 是一个正方形,除四条边长度相同外,还满足每条边都与 x-轴 或 y-轴 平行或垂直。

实现 DetectSquares 类:

  • DetectSquares() 使用空数据结构初始化对象
  • void add(int[] point) 向数据结构添加一个新的点 point = [x, y]
  • int count(int[] point) 统计按上述方式与点 point = [x, y] 共同构造 轴对齐正方形 的方案数。

示例 1:

输入: ["DetectSquares", "add", "add", "add", "count", "count", "add", "count"] [[], [[3, 10]], [[11, 2]], [[3, 2]], [[11, 10]], [[14, 8]], [[11, 2]], [[11, 10]]] 输出: [null, null, null, null, 1, 0, null, 2]

哈希表法

初步的思路分析:我是想着先把同一列的上点找出来,然后可以根据边长把剩下两个点找出来即可,接下来就是数据结构的选择,因为是根据横纵两条射线来查找,所以两个哈希表就行,分别按照x、y坐标来存储,value没必要存列表,直接存一个Counter,后面拿出来直接加。具体的实现思路如下:

  • 数据结构用哈希表来存储位置和每个位置上点的个数

  • 计算正方形时,先找和输入点point[x,y]横坐标x相同的点集合xSet,然后对于同一个横坐标下,每一个不同的纵坐标y1计算正方形的边长length,这样我们就固定下一条平行于y轴的线

  • 接着判断哈希表中,是否存在横坐标为x - length或x + length的点,对找到横坐标的哈希集合,判断其中是否同时存在y和y1,是则计算正方形的个数

class DetectSquares {
    Map<Integer, Map<Integer, Integer>> xPointsCount; // x -> {y1:count, y2:count}

    public DetectSquares() {
        xPointsCount = new HashMap<>();
    }

    public void add(int[] point) {
        if (!xPointsCount.containsKey(point[0])) xPointsCount.put(point[0], new HashMap<>());
        xPointsCount.get(point[0]).put(point[1], xPointsCount.get(point[0]).getOrDefault(point[1], 0) + 1);
    }

    public int count(int[] point) {
        int x12 = point[0], y14 = point[1], res = 0;
        for (int y23 : xPointsCount.getOrDefault(x12, new HashMap<>()).keySet()) {
            if (y23 == y14) continue;
            int count2 = xPointsCount.get(x12).get(y23); 
            int edge = Math.abs(y23 - y14);
            res += count2 * xPointsCount.getOrDefault(x12 + edge, new HashMap<>()).getOrDefault(y23, 0) *
                    xPointsCount.getOrDefault(x12 + edge, new HashMap<>()).getOrDefault(y14, 0) +
                    count2 * xPointsCount.getOrDefault(x12 - edge, new HashMap<>()).getOrDefault(y23, 0) *
                            xPointsCount.getOrDefault(x12 - edge, new HashMap<>()).getOrDefault(y14, 0);
        }
        return res;
    }
}

最后

温馨提示:看不懂题目就画个图吧,一图解千惑啊,其实这个题目和我大学时参加的省赛中的某一题有些相似,那个稍微简单一些,是给你四个点坐标,判断围绕起来是否是矩形。本题在难搞题目的基础上,加上计数的方式。