题目描述
思路解析动画文字版
核心:先锁一条竖边定出边长,正方形剩下两个角就唯一确定,去集合里查它们在不在、各有几个。
数据结构就一个计数哈希表 cnt;难点全在 count 里怎么由一条竖边推出另两个角。
一开始集合是空的,平面上灰色的位置是接下来要加入的点,先认认它们的坐标。
add (1,1):把点 (1,1) 加进集合,它的次数记为 1(绿色就是刚加入的这个点)。
add (1,4):把点 (1,4) 加进集合,它的次数记为 1(绿色就是刚加入的这个点)。
add (4,1):把点 (4,1) 加进集合,它的次数记为 1(绿色就是刚加入的这个点)。
add (4,4):把点 (4,4) 加进集合,它的次数记为 1(绿色就是刚加入的这个点)。
count(1,1):把 (1,1) 设为查询点 q(蓝色高亮)。目标是数出有多少个轴对齐正方形以它为一个角。answer 先记 0。
遍历集合里每个点,挑「和 q 同列(x=1)且不同行」的当竖边搭档。先看 (4,4):它的 x=4,和 q 不同列,跳过。
再看 (4,1):x=4 不同列(而且还和 q 同一行),不能当竖边搭档,跳过。
看 (1,4):x=1 和 q 同列、y=4 又不同行,正好符合,选它当竖边搭档(蓝色)。
q(1,1) 和搭档 p(1,4) 构成左侧竖边,边长 side = |4 − 1| = 3。边长一定,正方形另外两个角就被钉死了。
向右展开:第三个角应是 (qx+side, qy)=(4,1)。去集合里查,(4,1) 存在、出现 1 次(橙色标出)。
第四个角应是 (qx+side, py)=(4,4)。集合里也有、出现 1 次。四个角凑齐,这是一个合法的正方形。
把搭档、右下角、右上角三个点的次数相乘:1×1×1=1。answer 累加,变成 1(四个角一起高亮成绿色)。
同一条竖边还能往左展开:左侧两个角是 (−2,1) 和 (−2,4),集合里都没有,所以左侧贡献 0 个。
同一列 x=1 里,除了 (1,4) 再没有别的点可当竖边搭档,遍历到此结束。
整趟只数出一个正方形(高亮的四个角),count(1,1) 返回 answer = 1,这就是最终答案。
若此时再 add(4,4) 一次,它的次数变成 2,同一个正方形的方案数就按次数相乘变成 1×1×2=2——这就是为什么要相乘而不是只判存在。
再演一遍 count(4,1):把 (4,1) 设为查询点 q(蓝色)。同样要数以它为一个角的正方形,answer 重新从 0 开始。
在 x=4 这一列里找搭档:(4,4) 同列且不同行,选它。竖边 (4,1)—(4,4) 的边长 side=3。
这次查询点在右边,往左展开:另两个角是 (1,1) 和 (1,4),集合里都在(橙色标出)。四角凑齐,又是一个正方形。
相乘累加得 1。注意这和前面 count(1,1) 数到的是「同一个正方形」,只是从不同的角出发去数——返回值仍是 1。
三个高频追问:为何记次数、为何只遍历竖边搭档把复杂度降到 O(n)、横竖边等价。
参考代码
class DetectSquares: def __init__(self): self.cnt = collections.Counter() # 点 -> 次数 def add(self, p): self.cnt[(p[0], p[1])] += 1 def count(self, p): qx, qy = p ans = 0 for (px, py), c in self.cnt.items(): if px != qx or py == qy: # 只要同列且不同行的搭档 continue side = abs(py - qy) for dx in (side, -side): # 向右 / 向左 ans += c * self.cnt[(qx+dx, qy)] * self.cnt[(qx+dx, py)] return ans复杂度
- add:O(1),哈希表里给对应点的次数加一
- count:O(n),n 为集合里不同点的个数,遍历一遍找竖边搭档,每个搭档查另两角是 O(1)
- 空间:O(n),cnt 哈希表存每个不同点及其次数
易错点
面试追问把动画讲成自己的话
追问为什么用「点→次数」的哈希表,而不是只用集合 set?
追问count 里为什么只遍历「竖边搭档」而不是枚举所有点对?
追问查询点和搭档也可以选成「横边」吗?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
回文数
LeetCode 9 · 简单 · 沿着 数学 & 几何 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题