几何算法实战:力扣LCP42"玩具套圈"问题的解法详解与优化思路
一、问题描述
给定一组玩具的坐标toys
和一组圆环的坐标及半径circles
,要求计算有多少个玩具能被至少一个圆环套住。每个圆环由(x,y,r)表示,其中(x,y)是圆心坐标,r是半径。
示例:
输入:toys = [[3,3],[1,2]], circles = [[4,3,1],[3,3,1],[1,2,2]]
输出:2
解释:两个玩具都能被至少一个圆环套住
二、解题思路
采用"暴力枚举+几何判断"策略:
遍历每个玩具
对于每个玩具,检查是否存在至少一个圆环能套住它
判断条件是玩具到圆心的距离 ≤ 圆环半径
三、算法详解
#include <vector> #include <cmath> using namespACe std; class Solution { public: int circleGame(vector<vector<int>>& toys, vector<vector<int>>& circles, int r) { int count = 0; for (const auto& toy : toys) { int tx = toy[0], ty = toy[1], tr = toy[2]; // 玩具半径必须小于等于套圈半径才可能被套住 if (tr > r) continue; bool covered = false; for (const auto& circle : circles) { int cx = circle[0], cy = circle[1]; // 计算两点间距离平方(避免浮点运算) long dx = tx - cx, dy = ty - cy; long distance_sq = dx * dx + dy * dy; long max_distance = r - tr; // 比较距离平方与半径平方差 if (distance_sq <= max_distance * max_distance) { covered = true; break; } } if (covered) count++; } return count; } };
四、算法详解
1. 几何判断原理
玩具被圆环套住的条件:玩具中心到圆心的距离 + 玩具半径 ≤ 圆环半径
使用欧几里得距离公式:√((x2-x1)² + (y2-y1)²)
2. 优化思路
空间分区:将圆环按空间划分,减少需要检查的圆环数量
排序预处理:按圆环半径排序,优先检查大圆环
距离平方比较:避免开平方运算,比较距离平方
3. 边界条件处理
玩具半径大于圆环半径的情况
多个圆环重叠的情况
玩具正好在圆环边缘的情况
空输入的处理
五、关键点解析
1. 几何条件理解
玩具完全在圆环内 ≠ 玩具中心在圆环内
需要考虑玩具自身的半径(tr)
实际判断的是两个圆的包含关系
2. 浮点数处理
使用sqrt和pow会引入浮点运算
实际比赛中可以比较距离平方避免浮点误差
工业场景需要考虑数值稳定性
3. 复杂度分析
时间复杂度:O(n*m) 最坏情况下需要检查所有组合
空间复杂度:O(1) 只使用了常数额外空间
六、常见错误分析
原创内容 转载请注明出处