来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/detect-squares
题目描述
给你一个在 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
解题思路
从提示来看,x和y的坐标范围是[0,1000],所以考虑使用二维数组来存储点的位置,二维数组的值表示该位置的点数量,这样解决重复的问题。
对于add函数,只需要将二维数组中对应的值增加1就可以了,复杂度为O(1).
对于count函数,需要遍历查询点(x1, y1)所在的列的点(x1, y2),对于(x1,y2),通过点和查询点的y坐标可以得出正方形的边长L,即可计算出另外两个点应该是(x1 - L, y1)、(x1 - L,y2) 或(x1 + L, y1)、(x1 + L,y2)将他们是二维数组中数目相乘就是数量。
代码展示
class DetectSquares { public: int aaiCanvas[1001][1001]; DetectSquares() { memset(aaiCanvas, 0, sizeof(aaiCanvas)); } void add(vector<int> point) { aaiCanvas[point[0]][point[1]]++; } int count(vector<int> point) { int iRet = 0; for(int i = 0; i < 1001; i++) { if(i != point[0]) { if(aaiCanvas[i][point[1]] != 0) { int iLength = abs(point[0] - i); if(point[1] - iLength >= 0) { iRet += aaiCanvas[i][point[1]] * aaiCanvas[i][point[1] - iLength] * aaiCanvas[point[0]][point[1] - iLength]; } if(point[1] + iLength < 1001) { iRet += aaiCanvas[i][point[1]] * aaiCanvas[i][point[1] + iLength] * aaiCanvas[point[0]][point[1] + iLength]; } } } } return iRet; } }; /** * Your DetectSquares object will be instantiated and called as such: * DetectSquares* obj = new DetectSquares(); * obj->add(point); * int param_2 = obj->count(point); */
运行结果
进阶
使用双重哈希map来代替二维数组可以提高更多的效率。