lc2013 Detect Squares - LeetCode
给你一个在 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]
提示:
point.length == 2
0 <= x, y <= 1000
调用 add 和 count 的 总次数 最多为 5000
# 解题思路
1.构造函数:创建一个邻接表,默认值设置为 int
2. add方法:使用哈希表记录下所有点出现的次数:key是坐标,value是该坐标出现的次数
2. count方法:传入一个点名字为 point,坐标为(x,y),问你这个点能够构成多少个正方形。思路其实非常简单:遍历哈希表里面所有已经记录下来的点,每个点暂时记录为 (x1, y1)。如果说point和当前这个点能构成一个正方形,那么一定满足:
1. 两个坐标不是同一个坐标(x != x1, y != y1)
2. 两个坐标之间横纵坐标的绝对值差是相等的:abs(x-x1) == abs(y-y1)
3. 遍历的这个点(x1, y1),其实是 point 对角线上的这个点!因为只有直到对角线上点的坐标,才能够轻易推出剩下两个点的坐标,所以才会有那句 x != x1, y != y1,来排除掉和 point 直接相邻的点!
示意图:
point (x, y ) ----------------------------------- (x1, y) if x == x1, continue
| |
| |
(x, y1) ______________________(x1,y1) - 遍历中真正要找的点!
if y == y1, continue
# 解题代码:
class DetectSquares(object):
def __init__(self):
self.d = collections.defaultdict(int)
def add(self, point):
"""
:type point: List[int]
:rtype: None
"""
self.d[tuple(point)] += 1
def count(self, point):
"""
:type point: List[int]
:rtype: int
"""
px,py = point
res = 0
for x, y in self.d.keys():
if (abs(px-x) != abs(py-y)) or px == x or py == y:
continue
res += self.d[(x,py)] * self.d[(px,y)] * self.d[(x,y)]
return res
# 易错点分析:
1.一开始的边界问题可以问什么?
x和y坐标的范围是什么;point数组的长度是什么,constriant里面的问题就是我应该要在面试过程去和面试官求证的问题。
2. 遍历哈希里面的点的时候,其实是在遍历哪个点?
其实是在寻找对角线上面的那个点,通过对角线那个点推出另外两个坐标为(x,y1), (x1,y),那么就能够凑齐(x,y1), (x1,y),(x,y)这三个点的坐标。找到之后, 就直接去哈希表里面查看,这三个点是否存在,如果存在,就是三个点出现的频率相乘
3. 为什么defaultdict的默认值一定要写int?
因为不写的话,如果(x,y1), (x1,y),(x,y) 其中任意一个点在dic里面不存在的话,就会报key error的错误。所以默认值写成int是为了避免key error
4. 为什么 for x1, y1 in d.keys() 会报 Dictionary Changed Size During Iteration Python 3 的错?
大概是说字典在遍历时不能进行修改,建议转成列表或集合处理。
例如:list(my_dict.keys())
和list(my_dict)
的结果都是字典的键的列表但是我尝试把self.d进行深度拷贝,结果也并没有顺利通过和运行。同样的代码,在python2能够顺利通过,但是在python3就是不能通过的。
# 时空复杂度:
时间:O(N)构建哈希表所需要的时间
空间:O(N)哈希表存储的元素数量