LeetCode 1037题解:向量叉积判断三点共线性

发布时间:2026/7/27 19:10:48

LeetCode 1037题解:向量叉积判断三点共线性 1. 题目解析理解回旋镖的几何定义LeetCode 1037题要求判断给定的三个点是否能构成一个有效的回旋镖。在几何学中回旋镖形状可以理解为三个点不共线且能形成一个有方向的角。具体来说三个点必须互不相同它们不能位于同一条直线上这三个点应该能形成一个有面积的三角形数学上判断三点共线性的经典方法是计算向量叉积。给定三个点A(x1,y1)、B(x2,y2)、C(x3,y3)我们可以构造两个向量AB向量(x2-x1, y2-y1)AC向量(x3-x1, y3-y1)这两个向量的叉积结果为(x2-x1)(y3-y1) - (y2-y1)(x3-x1)。如果这个结果等于0说明三点共线否则三点不共线可以构成回旋镖。2. 解题思路与算法选择2.1 向量叉积法这是最直接和高效的解决方案时间复杂度O(1)空间复杂度O(1)。实现步骤检查三个点是否完全相同虽然题目保证输入都是不同的点但好的习惯是加上这个检查计算AB和AC两个向量计算这两个向量的叉积判断叉积结果是否为0C实现示例bool isBoomerang(vectorvectorint points) { // 提取三个点的坐标 int x1 points[0][0], y1 points[0][1]; int x2 points[1][0], y2 points[1][1]; int x3 points[2][0], y3 points[2][1]; // 计算向量AB和AC的叉积 int cross (x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1); return cross ! 0; }2.2 斜率比较法另一种思路是比较AB和AC两条边的斜率计算AB边的斜率(y2-y1)/(x2-x1)计算AC边的斜率(y3-y1)/(x3-x1)比较两个斜率是否相等这种方法需要注意处理垂直线x坐标相同的情况避免除以0的错误。虽然直观但实现起来比叉积法更复杂且涉及浮点数比较的精度问题。3. 代码实现细节与优化3.1 使用vector容器处理输入题目输入是vectorvector 类型每个内部vector表示一个点的x,y坐标。现代C中处理这种结构有几个技巧使用结构化绑定(C17)简化代码auto [x1, y1] points[0]; auto [x2, y2] points[1]; auto [x3, y3] points[2];避免不必要的拷贝使用const引用bool isBoomerang(const vectorvectorint points) { // ... }3.2 交叉相乘的数学原理叉积公式(x2-x1)(y3-y1) - (y2-y1)(x3-x1)实际上是二维向量叉积的定义。在二维情况下两个向量(a,b)和(c,d)的叉积等于ad - bc。这个值的绝对值等于这两个向量所张平行四边形的面积。当叉积为0时表示两个向量共线平行三点在同一直线上非零值表示三点可以形成三角形即有效的回旋镖。4. 常见错误与边界情况4.1 浮点数精度问题有些初学者尝试用斜率法实现但会遇到浮点数比较的精度问题。例如double slope1 (y2-y1)/(double)(x2-x1); double slope2 (y3-y1)/(double)(x3-x1); if(slope1 slope2) { ... } // 不推荐这种比较方式更安全的方式是交叉相乘保持整数运算if((y2-y1)*(x3-x1) (y3-y1)*(x2-x1)) { ... }4.2 点重合的特殊情况虽然题目说明三个点都是不同的但在实际编程中应该考虑if(points[0] points[1] || points[0] points[2] || points[1] points[2]) { return false; }4.3 处理垂直线和水平线叉积法天然处理了这些特殊情况垂直线x坐标相同但y坐标不同水平线y坐标相同但x坐标不同 不需要特殊处理算法依然有效5. 性能分析与优化5.1 时间复杂度无论使用叉积法还是斜率法时间复杂度都是O(1)因为只进行了固定数量的算术运算。5.2 空间复杂度O(1)没有使用额外的存储空间只用了几个局部变量存储坐标值。5.3 编译器优化现代编译器会对这类简单函数进行很好的优化。可以添加constexpr和noexcept关键字帮助编译器优化constexpr bool isBoomerang(const vectorvectorint points) noexcept { // ... }但要注意noexcept只表示函数不会抛出异常不影响算法正确性。6. 测试用例设计好的测试用例应该覆盖各种边界情况普通不共线三点{{1,1},{2,3},{3,2}} // 预期true共线三点{{1,1},{2,2},{3,3}} // 预期false水平线{{0,0},{1,0},{2,0}} // 预期false垂直线{{0,0},{0,1},{0,2}} // 预期false两点重合虽然题目保证不会出现{{0,0},{0,0},{1,1}} // 防御性编程应返回false所有点相同{{0,0},{0,0},{0,0}} // 防御性编程应返回false7. 不同语言实现对比7.1 Python实现Python可以利用元组解包简化代码def isBoomerang(points): (x1, y1), (x2, y2), (x3, y3) points return (x2 - x1) * (y3 - y1) ! (y2 - y1) * (x3 - x1)7.2 Java实现Java需要注意整数溢出问题public boolean isBoomerang(int[][] points) { return (points[1][0] - points[0][0]) * (points[2][1] - points[0][1]) ! (points[1][1] - points[0][1]) * (points[2][0] - points[0][0]); }7.3 JavaScript实现ES6解构赋值让代码更简洁const isBoomerang ([[x1,y1],[x2,y2],[x3,y3]]) (x2-x1)*(y3-y1) ! (y2-y1)*(x3-x1);8. 实际应用场景虽然这个问题看起来是纯数学问题但它的解法在实际中有重要应用计算机图形学判断点是否在三角形内多边形三角剖分等游戏开发碰撞检测视线判断地理信息系统判断多个地点是否在一条路径上机器人路径规划避免直线运动障碍物理解向量叉积的概念对解决更复杂的几何问题至关重要。9. 算法扩展与变种9.1 判断多点共线同样的方法可以扩展到判断多个点是否共线。对于n个点选择前两个点确定一条直线然后检查其他所有点是否都在这条直线上。9.2 计算多边形面积利用叉积可以计算简单多边形的面积。对于多边形顶点P1,P2,...,Pn面积为area 0.5 * |sum((x_i*y_{i1} - x_{i1}*y_i))|其中P_{n1} P1。9.3 点与线段的位置关系通过叉积可以判断点在线段的哪一侧这在很多几何算法中都有应用。10. 学习建议与刷题技巧理解几何基础掌握向量、点积、叉积等基本概念多画图辅助理解在纸上画出各种情况的点分布从简单方法入手先实现最直观的解法再考虑优化注意边界条件特别是涉及除法的解法要考虑分母为零的情况比较不同语言实现加深对算法本质的理解对于LeetCode刷题建议先独立尝试解决写出测试用例验证查看讨论区学习其他解法总结解题模式和技巧这道题虽然简单但体现了算法竞赛中常见的几何问题处理方式。掌握这类基础问题的解法能为解决更复杂的问题打下坚实基础。

相关新闻