doocs/leetcode 几何算法
还在为LeetCode几何算法题目头疼吗?一文带你掌握doocs/leetcode中几何算法的核心解题技巧!本文将深入解析三个经典几何算法题目:矩形面积II、直线上最多的点数、矩形面积,通过详细的代码示例、流程图和表格对比,让你彻底理解几何算法的精髓。
📊 几何算法概述
几何算法是计算机科学中处理几何图形和空间关系的重要分支,在LeetCode中主要涉及点、线、面等基本几何元素的计算和处理。doocs/leetcode项目提供了丰富的几何算法题解,涵盖了从简单到困难的各类几何问题。
几何算法核心概念
| 概念 | 描述 | 应用场景 |
|---|---|---|
| 点(Point) | 二维平面上的坐标位置 | 判断点是否在直线上、计算点之间的距离 |
| 线(Line) | 由两点确定的直线 | 判断多点共线、计算直线交点 |
| 面(Plane) | 由边界确定的二维区域 | 计算矩形面积、判断区域重叠 |
| 向量(Vector) | 有方向和大小的量 | 计算斜率、判断方向关系 |
🔢 850. 矩形面积 II
问题描述
给定多个轴对齐的矩形,计算它们覆盖的总面积。任何被两个或多个矩形覆盖的区域应只计算一次。
算法思路
核心代码实现
class Node:
def __init__(self):
self.l = self.r = 0
self.cnt = self.length = 0
class SegmentTree:
def __init__(self, nums):
n = len(nums) - 1
self.nums = nums
self.tr = [Node() for _ in range(n << 2)]
self.build(1, 0, n - 1)
def build(self, u, l, r):
self.tr[u].l, self.tr[u].r = l, r
if l != r:
mid = (l + r) >> 1
self.build(u << 1, l, mid)
self.build(u << 1 | 1, mid + 1, r)
def modify(self, u, l, r, k):
if self.tr[u].l >= l and self.tr[u].r <= r:
self.tr[u].cnt += k
else:
mid = (self.tr[u].l + self.tr[u].r) >> 1
if l <= mid:
self.modify(u << 1, l, r, k)
if r > mid:
self.modify(u << 1 | 1, l, r, k)
self.pushup(u)
def pushup(self, u):
if self.tr[u].cnt:
self.tr[u].length = self.nums[self.tr[u].r + 1] - self.nums[self.tr[u].l]
elif self.tr[u].l == self.tr[u].r:
self.tr[u].length = 0
else:
self.tr[u].length = self.tr[u << 1].length + self.tr[u << 1 | 1].length
class Solution:
def rectangleArea(self, rectangles: List[List[int]]) -> int:
segs = []
alls = set()
for x1, y1, x2, y2 in rectangles:
segs.append((x1, y1, y2, 1))
segs.append((x2, y1, y2, -1))
alls.update([y1, y2])
segs.sort()
alls = sorted(alls)
tree = SegmentTree(alls)
m = {v: i for i, v in enumerate(alls)}
ans = 0
for i, (x, y1, y2, k) in enumerate(segs):
if i:
ans += tree.length * (x - segs[i - 1][0])
tree.modify(1, m[y1], m[y2] - 1, k)
ans %= int(1e9 + 7)
return ans
复杂度分析
| 操作 | 时间复杂度 | 空间复杂度 |
|---|---|---|
| 排序y坐标 | O(n log n) | O(n) |
| 构建线段树 | O(n) | O(n) |
| 扫描线处理 | O(n log n) | O(1) |
| 总计 | O(n log n) | O(n) |
📈 149. 直线上最多的点数
问题描述
给定一个点集,求最多有多少个点在同一条直线上。
算法思路
核心代码实现
class Solution:
def maxPoints(self, points: List[List[int]]) -> int:
def gcd(a, b):
return a if b == 0 else gcd(b, a % b)
n = len(points)
ans = 1
for i in range(n):
x1, y1 = points[i]
cnt = Counter()
for j in range(i + 1, n):
x2, y2 = points[j]
dx, dy = x2 - x1, y2 - y1
g = gcd(dx, dy)
k = (dx // g, dy // g)
cnt[k] += 1
ans = max(ans, cnt[k] + 1)
return ans
斜率处理技巧
为了避免浮点数精度问题,我们使用最简分数形式表示斜率:
复杂度分析
| 方法 | 时间复杂度 | 空间复杂度 | 优点 | 缺点 |
|---|---|---|---|---|
| 暴力枚举 | O(n³) | O(1) | 简单直观 | 效率低 |
| 哈希表优化 | O(n² log m) | O(n) | 效率较高 | 需要处理精度问题 |
🟦 223. 矩形面积
问题描述
计算两个轴对齐矩形的覆盖总面积,需要考虑重叠区域。
算法思路
核心代码实现
class Solution:
def computeArea(
self,
ax1: int, ay1: int, ax2: int, ay2: int,
bx1: int, by1: int, bx2: int, by2: int
) -> int:
# 计算两个矩形的面积
area1 = (ax2 - ax1) * (ay2 - ay1)
area2 = (bx2 - bx1) * (by2 - by1)
# 计算重叠区域的宽度和高度
width = min(ax2, bx2) - max(ax1, bx1)
height = min(ay2, by2) - max(ay1, by1)
# 计算重叠区域面积(如果无重叠则为0)
overlap = max(width, 0) * max(height, 0)
return area1 + area2 - overlap
重叠区域计算原理
边界情况处理
| 情况 | 描述 | 处理方式 |
|---|---|---|
| 无重叠 | width或height为负数 | max(0, value) |
| 完全包含 | 一个矩形完全在另一个内部 | 正常计算重叠区域 |
| 边接触 | 矩形边重合但无面积重叠 | width或height为0 |
📋 几何算法解题技巧总结
1. 坐标处理技巧
# 计算两点间距离
def distance(x1, y1, x2, y2):
return math.sqrt((x2 - x1)**2 + (y2 - y1)**2)
# 计算向量叉积(判断方向)
def cross_product(x1, y1, x2, y2):
return x1 * y2 - x2 * y1
# 计算点积(判断夹角)
def dot_product(x1, y1, x2, y2):
return x1 * x2 + y1 * y2
2. 常见几何问题分类
| 问题类型 | 典型题目 | 解决思路 |
|---|---|---|
| 点线关系 | 149.直线上最多的点数 | 斜率统计、向量共线 |
| 面积计算 | 223.矩形面积、850.矩形面积II | 扫描线、线段树 |
| 相交判断 | 836.矩形重叠 | 边界比较、投影分析 |
| 最近点对 | 经典问题 | 分治法、平面扫描 |
3. 精度处理建议
# 使用分数避免浮点误差
from fractions import Fraction
# 或者使用最大公约数标准化
def normalize_slope(dx, dy):
if dx == 0 and dy == 0:
return (0, 0)
if dx == 0:
return (0, 1)
if dy == 0:
return (1, 0)
g = math.gcd(abs(dx), abs(dy))
if dx < 0: # 统一让dx为正
dx, dy = -dx, -dy
return (dx // g, dy // g)
🚀 实战演练
练习题目推荐
-
简单级别
-
- 矩形面积 - 掌握基本重叠区域计算
-
- 矩形重叠 - 判断矩形是否相交
-
-
中等级别
-
- 直线上最多的点数 - 斜率统计与精度处理
-
- 安装栅栏 - 凸包算法应用
-
-
困难级别
-
- 矩形面积 II - 扫描线与线段树
-
- 完美矩形 - 复杂区域覆盖判断
-
学习路径建议
💡 总结
通过本文的学习,你应该已经掌握了doocs/leetcode中几何算法的核心解题技巧:
- 矩形面积计算:理解重叠区域的处理方法,掌握扫描线算法和线段树的应用
- 点线关系分析:学会使用哈希表统计斜率,避免浮点数精度问题
- 算法优化思路:从暴力解法到优化解法的演进路径
几何算法虽然看似复杂,但只要掌握核心的数学原理和数据结构应用,就能有效解决各类几何问题。建议多练习相关题目,培养空间思维能力,在实际编程中注意处理边界情况和精度问题。
继续深入学习可以探索计算几何的更多领域,如凸包算法、最近点对问题、多边形处理等,这些知识在图形学、GIS系统、游戏开发等领域都有广泛应用。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



