2013-检测正方形
给你一个在 X-Y 平面上的点构成的数据流。设计一个满足下述要求的算法:
- 添加 一个在数据流中的新点到某个数据结构中 。 可以添加 重复 的点,并会视作不同的点进行处理。
- 给你一个查询点,请你从数据结构中选出三个点,使这三个点和查询点一同构成一个 面积为正 的 轴对齐正方形 , 统计 满足该要求的方案数目 。
轴对齐正方形 是一个正方形,除四条边长度相同外,还满足每条边都与 x-轴 或 y-轴 平行或垂直。
实现 DetectSquares
类:
DetectSquares()
使用空数据结构初始化对象void add(int[] point)
向数据结构添加一个新的点point = [x, y]
int count(int[] point)
统计按上述方式与点point = [x, y]
共同构造 轴对齐正方形 的方案数。
示例:
**输入:**
["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]
**解释:**
DetectSquares detectSquares = new DetectSquares();
detectSquares.add([3, 10]);
detectSquares.add([11, 2]);
detectSquares.add([3, 2]);
detectSquares.count([11, 10]); // 返回 1 。你可以选择:
// - 第一个,第二个,和第三个点
detectSquares.count([14, 8]); // 返回 0 。查询点无法与数据结构中的这些点构成正方形。
detectSquares.add([11, 2]); // 允许添加重复的点。
detectSquares.count([11, 10]); // 返回 2 。你可以选择:
// - 第一个,第二个,和第三个点
// - 第一个,第三个,和第四个点
提示:
point.length == 2
0 <= x, y <= 1000
- 调用
add
和count
的 总次数 最多为5000
方法一:哈希表
思路
先考虑如何实现 int count(int[] point)
,记输入的 point 的横纵坐标分别为 x 和 y。则形成的正方形的上下两条边中,其中一条边的纵坐标为 y, 我们枚举另一条边的纵坐标为 col,则正方形的边长 d 为 |y - col| 且大于 0。有了其中一个点的坐标 (x, y) 和一条横边的纵坐标 col,我们可以得到正方形的四个点的坐标分别为 (x, y),(x, col),(x+d, y),(x+d, col) 或 (x, y),(x, col),(x-d, y),(x-d, col)。
据此,我们可以用一个哈希表来存储 void add(int[] point)
函数中加入的点。先把点按照行来划分,键为行的纵坐标,值为另一个哈希表,其中键为该行中的点的横坐标,值为这样的点的个数。因为点会重复出现,所以计算正方形的个数时需要把另外三个坐标出现的次数相乘。
代码
1 | class DetectSquares: |
1 | class DetectSquares { |
1 | public class DetectSquares { |
1 | class DetectSquares { |
1 | typedef struct { |
1 | var DetectSquares = function() { |
1 | type DetectSquares map[int]map[int]int |
复杂度分析
时间复杂度:
DetectSquares()
消耗 O(1) 时间复杂度,void add(int[] point)
消耗 O(1) 时间复杂度,int count(int[] point)
消耗 O(n) 时间复杂度,其中 n 为void add(int[] point)
已经调用的次数。空间复杂度:
DetectSquares()
消耗 O(1) 空间复杂度,void add(int[] point)
消耗 O(1) 空间复杂度,int count(int[] point)
消耗 O(1) 空间复杂度。