题目描述
算法分析 这道题目看起来难度不高,判断多点共线问题似乎是高中数学里面就学过的算法思路。 所以一开始,我的算法思路和斜率有关。 可以根据“两点确定一条直线”,可以算出一个参考的斜率,根据参考的斜率预测下一个坐标点的位置(可以已知x坐标求y坐标)。 或者每个点都和第一个点进行斜率计算,得出的结果如果总是相同,则多点共线。
而大佬们的算法博客中,思路基本上也是如此:计算第i个点、第i-1个点、第i+1个点之间的斜率;【Java解法、C语言解法】 计算第0个点、第1个点、第i个点之间的斜率;【python解法】 利用直线方程进行求解【C++解法】
此外,需要注意的是,比较斜率时,为了避免除0这种特殊错误的产生,可以将除法式转化为乘法式,当这样比较斜率时,也可以说是运用了向量共线的基本性质。
代码实现 【C】
/*
采用向量之间的叉乘做法:
* 叉乘 a * b
* = | x1, y1 | = x1 * y2 - y1 * x2
* | x2, y2 |
* 若结果小于 0,表示向量 b 在向量 a 的顺时针方向;
* 若结果大于 0,表示向量 b 在向量 a 的逆时针方向;
* 若结果为 0,表示向量 b 与向量 a 平行;
*/
bool checkStraightLine(int** coordinates, int coordinatesSize, int* coordinatesColSize)
{
int x1 = coordinates[1][0] - coordinates[0][0];
int y1 = coordinates[1][1] - coordinates[0][1];
for (int i = 2; i < coordinatesSize; ++i) {
int x2 = coordinates[i][0] - coordinates[0][0];
int y2 = coordinates[i][1] - coordinates[0][1];
if (x1 * y2 != x2 * y1) {//和比较斜率很相似,比较的是第i个、第0个、第1个点之间的斜率是否相同。
return false;
}
}
return true;
}
C语言参考网址
【C++】
/*
采用直线方程的求解方法。
设定一个线性方程,代入点坐标求解系数,得到一条参考的直线,之后在印证其他的点是不是在这条直线上。
为了线性方程的系数求解简单,该解法中先做了平移,简化直线方程
*/
class Solution {
public:
bool checkStraightLine(vector<vector<int>> &coordinates) {
int deltaX = coordinates[0][0], deltaY = coordinates[0][1];//平移程度
int n = coordinates.size();
for (int i = 0; i < n; ++i) {//将所有的点进行平移,数组中第一点此时位于原点,这样做是为了简化方程。
coordinates[i][0] -= deltaX;
coordinates[i][1] -= deltaY;
}
int A = coordinates[1][1], B = -coordinates[1][0];//Ax+By=0的方程中,带入point[0]和point[1],得到A、B两个系数大小。
for (int i = 2; i < n; ++i){//对于point[2]及之后的点,进行直线位置判断
int x = coordinates[i][0], y = coordinates[i][1];
if (A * x + B * y != 0) {
return false;
}
}
return true;
}
};
C++参考网址
【Java】
/*
利用斜率进行判断,如果相邻线段之间斜率总是相等,则点共线
*/
class Solution {
public boolean checkStraightLine(int[][] coordinates) {
int len = coordinates.length;
for (int i = 1; i < len - 1; ++i) {//遍历点坐标数组
int y1 = coordinates[i][1] -coordinates[i-1][1];//第i个点和第i-1个点之间的纵坐标差
int x1 = coordinates[i][0] -coordinates[i-1][0];//第i个点和第i-1个点之间的横坐标差
int y2 = coordinates[i+1][1] -coordinates[i][1]; //第i+1个点和第i个点之间的纵坐标差
int x2 = coordinates[i+1][0] -coordinates[i][0];//第i+1个点和第i个点之间的横坐标差
if (y1*x2 != y2*x1) {//y1/x1 y2/x2是两个斜率,此处进行化简,也就是判断两线段斜率是否相同,如果不同,则不共线
return false;
}
}
return true;
}
}
Java参考网址
【python】
#比较第0个,第1个和第i个点的斜率
class Solution:
def checkStraightLine(self, coordinates):
for i in range(2,len(coordinates)):
if (coordinates[i][1] - coordinates[1][1])*(coordinates[1][0]-coordinates[0][0]) != (coordinates[1][1] - coordinates[0][1]) * (coordinates[i][0] - coordinates[1][0]):#将除法转为乘法,目的是为了避免除0的情况
return False
return True
python参考网址