题目描述
思路解析动画文字版
枚举所有三点组合太慢。
把点计数存起来;查询时枚举对角点,另外两个角由坐标直接确定。
① 以查询点 (3,2) 为一角,数轴对齐正方形:count([3,2]):把查询点当正方形的一个角,枚举「对角点」,看能凑出多少个轴对齐正方形。
② 枚举对角点:需 |Δx|==|Δy| 且 ≠ 0:遍历已加入的点当对角点:(3,10) Δx=0 同列跳过;(11,2) Δx≠Δy 跳过;(11,10) Δx=8==Δy=8 且非 0 → 合法对角点。
③ 对角点 (11,10) 定了 → 另两角 (11,2)、(3,10):对角点 (11,10) 一确定,正方形另外两角就是 (对角x,查询y)=(11,2) 和 (查询x,对角y)=(3,10)。
④ 三个角都存在 → 方案数 = 出现次数相乘:对角点 + 两邻角都在 map 里 → 这种正方形的个数 = 三点出现次数的乘积 = 1×1×1 = 1。
⑤ 累加所有合法对角点 → count([3,2]) = 1:对每个合法对角点的乘积求和。本例只有 (11,10) 一个合法对角 → 总数 = 1。
一句话记住:把点计数存起来;查询时枚举对角点,另外两个角由坐标直接确定。
边界三连:本题真边界:无解、重复点、退化对角。
⑥ 雷区:为何要 Δx==Δy≠0、为何用乘积:① Δx==Δy 保证四边等长(轴对齐正方形),≠0 排除退化(同点/同线)。② 用乘积是因为同一坐标可能被 add 多次,每个角各有出现次数,组合数 = 三者相乘。枚举对角点天然覆盖四个方向,不会重复也不会漏。
面试追问 · 核心思路:思路:Counter 存点;count 枚举对角点,另两角乘积累加。
面试追问 · 为何枚举对角点:对角点定一个正方形,O(n) 枚举;枚举边对要 O(n²)。
面试追问 · 复杂度:复杂度:add O(1),count O(n),空间 O(n)。
这题学完不要乱跳,下一步去对应专题 /leetcode-animation/ds?k=math 连刷同类题;卡住时用 AI 答疑问“为什么枚举对角点就够”。
参考代码
class DetectSquares: def __init__(self): from collections import Counter self.points = Counter() def add(self, point): self.points[tuple(point)] += 1 def count(self, point): x, y = point ans = 0 for (px, py), cnt in self.points.items(): if px == x or abs(px - x) != abs(py - y): # 同列跳过 + 等边长 continue ans += cnt * self.points[(x, py)] * self.points[(px, y)] return ans复杂度
- 时间复杂度:add O(1) / count O(n),add 计数 O(1);count 遍历所有不同点找对角
- 空间复杂度:O(n),Counter 存所有加入过的点
可套用的代码模板
记牢:Counter 存点 → 枚举对角点(|Δx|==|Δy|≠0) → 另两角次数相乘累加。
Python
# 检测正方形(枚举对角点)骨架points = Counter()def add(p): points[tuple(p)] += 1def count(x, y): ans = 0 for (px, py), c in points.items(): # 枚举对角点 if abs(px-x) != abs(py-y) or px == x: continue # 等边长且非退化 ans += c * points[(px, y)] * points[(x, py)] # 另两角乘积 return ans易错点
面试追问把动画讲成自己的话
追问整体思路是什么?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
回文数
LeetCode 9 · 简单 · 沿着 数学 & 几何 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题