小M的回旋镖问题:判定三点是否构成回旋镖 | 豆包MarsCode AI刷题

179 阅读4分钟

前言

几何问题一直是数学和编程中的经典题目之一,尤其是涉及到平面上的三点判定问题。小M正在玩一个几何游戏,她需要判断给定的三点是否构成回旋镖。什么是回旋镖?简单来说,回旋镖就是三点不在同一条直线上,且这三点互不相同。如何高效判断三点是否构成回旋镖呢?这次我们就来一步步分析和解决这个问题。

问题描述

给定一个二维平面上的三个点 points,其中每个点用坐标表示为 points[i] = [xi, yi]。判断这三个点是否构成回旋镖,满足条件如下:

  1. 三个点不在同一条直线上;
  2. 三个点互不相同。

示例

  • 示例1:

    • 输入:points = [[1, 1], [2, 3], [3, 2]]
    • 输出:True
    • 解释:这三点不在同一条直线上,构成回旋镖。
  • 示例2:

    • 输入:points = [[1, 1], [2, 2], [3, 3]]
    • 输出:False
    • 解释:这三点在同一条直线上,不构成回旋镖。
  • 示例3:

    • 输入:points = [[0, 0], [1, 1], [1, 0]]
    • 输出:True
    • 解释:这三点不在同一条直线上,构成回旋镖。

image.png

解题思路

1. 判断三点是否互不相同

首先,我们需要检查三点是否是不同的点。如果有两个或更多的点相同,那么它们显然无法构成回旋镖。

2. 判断三点是否在同一条直线上

判断三点是否共线,是这道题的核心。我们可以通过计算两条线段的斜率来判断是否共线。为避免除法带来的精度问题,我们使用交叉乘法来代替斜率计算。

具体步骤是:

  • 对于三点 A(x1, y1)B(x2, y2)C(x3, y3) ,可以计算两个向量:

    • 向量 AB = (x2 - x1, y2 - y1)
    • 向量 BC = (x3 - x2, y3 - y2)
  • 如果这两个向量的叉积不为零,则三点不共线,构成回旋镖。

    • 叉积公式:(x2 - x1)*(y3 - y2) - (y2 - y1)*(x3 - x2)

3. 具体实现

我们将根据上述思路编写代码,判断三点是否满足回旋镖条件。

public class Main {
    public static boolean solution(int[][] points) {
        // 检查三点是否互不相同
        if (points[0][0] == points[1][0] && points[0][1] == points[1][1]) return false;
        if (points[0][0] == points[2][0] && points[0][1] == points[2][1]) return false;
        if (points[1][0] == points[2][0] && points[1][1] == points[2][1]) return false;
        
        // 计算两条线段的斜率(交叉乘法避免除法)
        int dx1 = points[1][0] - points[0][0];
        int dy1 = points[1][1] - points[0][1];
        int dx2 = points[2][0] - points[1][0];
        int dy2 = points[2][1] - points[1][1];

        // 如果斜率不同,则三点不共线,返回 true
        return dy1 * dx2 != dy2 * dx1;
    }

    public static void main(String[] args) {
        System.out.println(solution(new int[][]{{1, 1}, {2, 3}, {3, 2}}) == true);  // true
        System.out.println(solution(new int[][]{{1, 1}, {2, 2}, {3, 3}}) == false); // false
        System.out.println(solution(new int[][]{{0, 0}, {1, 1}, {1, 0}}) == true);  // true
    }
}

步骤1:检查三点是否互不相同

通过简单的条件判断,我们首先检查三个点是否相同。如果任意两个点相同,返回 false,否则继续执行后续的判断。

步骤2:计算斜率的交叉乘法

我们通过计算两条线段的斜率,判断三点是否共线。为了避免除法带来的精度问题,直接使用交叉乘法来判断斜率是否相等。若两条线段的斜率相等,则三点共线,返回 false;否则,返回 true

步骤3:返回结果

如果以上两个判断都通过,我们最终返回 true,表示这三个点构成回旋镖;否则返回 false


测试结果

  • 输入 points = [[1, 1], [2, 3], [3, 2]],输出 True
  • 输入 points = [[1, 1], [2, 2], [3, 3]],输出 False
  • 输入 points = [[0, 0], [1, 1], [1, 0]],输出 True

通过这些测试,我们可以看到代码准确地判断了三点是否构成回旋镖。


复杂度分析

时间复杂度

  • 检查点是否相同的操作是常数时间 O(1)
  • 计算斜率的交叉乘法也是常数时间 O(1)

因此,整个算法的时间复杂度是 O(1)

空间复杂度

  • 我们只使用了常数空间来存储输入的点坐标,因此空间复杂度是 O(1)

总结

通过简单的几何推理和交叉乘法,我们能够高效地解决三点是否构成回旋镖的问题。这道题考察了我们如何运用数学公式来避免浮动计算带来的误差,并通过编程实现了高效的判断方法。希望大家在解题过程中,能理解回旋镖问题的核心逻辑,并掌握如何优化算法,快速判断条件是否成立。