「这是我参与2022首次更文挑战的第27天,活动详情查看:2022首次更文挑战」。
题目描述:
1232. 缀点成线 - 力扣(LeetCode) (leetcode-cn.com)
给定一个数组 coordinates ,其中 coordinates[i] = [x, y] , [x, y] 表示横坐标为 x、纵坐标为 y 的点。请你来判断,这些点是否在该坐标系中属于同一条直线上。
示例一
输入: coordinates = [[1,2],[2,3],[3,4],[4,5],[5,6],[6,7]]
输出: true
示例二
示例三
输入: coordinates = [[1,1],[2,2],[3,4],[4,5],[5,6],[7,7]]
输出: false
提示:
- 2 <= coordinates.length <= 1000
- coordinates[i].length == 2
- -10^4 <= coordinates[i][0], coordinates[i][1] <= 10^4
- coordinates 中不含重复的点
思路分析
数学法
根据我们小学的数学知识即可知道,在给定的点集中,以任意一点 为基准,如果其他点的 是不变的,那么点集内所有的点在同一条直线上。
但是如果这些点连成的线是垂直于 轴的,即 为0,即涉及到除数为 的问题,需要单独判断。所以我们换个数学法。
我们可以把点集中除了 之外的点 都看成以 为起点、 为终点的向量,记为 ,并选择 作为基准。如果其他向量都与 共线,那么点集内所有的点共线。
这里需要用到线性代数的基础知识:如果二维向量 与 共线,那么它们线性相关,且有:
,即它们拼成的二阶矩阵的行列式为 。
AC代码
class Solution {
public boolean checkStraightLine(int[][] coordinates) {
int deltaX = coordinates[0][0], deltaY = coordinates[0][1];
int n = coordinates.length;
for (int i = 0; i < n; i++) {
coordinates[i][0] -= deltaX;
coordinates[i][1] -= deltaY;
}
int A = coordinates[1][1], B = -coordinates[1][0];
for (int i = 2; i < n; i++) {
int x = coordinates[i][0], y = coordinates[i][1];
if (A * x + B * y != 0) {
return false;
}
}
return true;
}
}
总结
同样的算法,用向量线性相关性来解释,逼格立马提升了N个档次 - -
参考
缀点成线 - 缀点成线 - 力扣(LeetCode) (leetcode-cn.com)
尽量不要用判断斜率是否相等,可以利用共线向量线性相关 - 缀点成线 - 力扣(LeetCode) (leetcode-cn.com)