点缀成线
简单的数学思维(我的思路)
只考虑两个点,在验证所有的点,先考虑x1 === x2 和 y1 === y2
然后考虑两个点的x的值可能为零,然后写出k,b的计算公式,最后用every判断一下。
/**
* @param {number[][]} coordinates
* @return {boolean}
*/
var checkStraightLine = function(coordinates) {
let x1 = coordinates[0][0]
let y1 = coordinates[0][1]
let x2 = coordinates[1][0]
let y2 = coordinates[1][1]
if (x1===x2){
return coordinates.every(item => {
return item[0] === x1
})
}else if(y1===y2){
return coordinates.every(item => {
return item[1] === y1
})
}
let b = ((y1*x2-x1*y2)/(x2-x1))
let k
if(x1===0){
k = (y2-b)/x2
}else {
k = (y1-b)/x1
}
return coordinates.every(item => {
return item[1] === k*item[0]+b
})
};
公式求b,真是一个sb的想法。。。。自己看了都尴尬。可以先用公式求k呀。(学过的数学全忘了)
向量计算
我们知道,在给定的点集中,以任意一点 P 为基准,如果所有其他点的k是不变的,那么点集内所有的点在同一条直线上。但是这种做法会涉及到除数为 0 的问题,即垂直于 x 轴的直线需要单独判断。而且在计算浮点除法运算时还会涉及到精度问题,虽然在力扣中通过应该是没问题的,但是如果把测试集稍微设计一下就可能会通过不了。所以我们最好另寻他法。
我们可以把点集中除了 P之外的点 P i都看成以 P为起点、P i为终点的向量,记为 vi,并选择 v1作为基准。如果其他向量都与 v 1 共线,那么点集内所有的点共线。
∣α, β∣=0,
即它们拼成的二阶矩阵的行列式为 0。
int n = coordinates.size();
int x0 = coordinates[0][0], y0 = coordinates[0][1];
int x = coordinates[1][0] - x0;
int y = coordinates[1][1] - y0;
for (int i = 2; i < n; ++i) {
int xi = coordinates[i][0] - x0;
int yi = coordinates[i][1] - y0;
if (x * yi - y * xi) { //计算二阶行列式
return false;
}
}
return true;
这个想法很是不错,很细致。