今天在LeetCode上做题有一点收获,特在此记录一下。那是一道简单题,简单描述,它给我一些点,我们判断这些点是不是都在一条直线上。(题目和链接见文章末)。
我首先考虑的就是先求前两个点的斜率,然后分别求后面所有点与第一个点的斜率,比较是否相等,如果不相等就直接返回false。若到了最后都相等,就返回true。在这里,要求斜率,则要求做除法,而除法则需要判断分子是否为0.所以我的具体做法是这样的:
1、判断第一个点和第二个点横坐标是否一样。如果一样,则进入2。如果不一样,则进入3。
2、判断剩下的点横坐标是否和第一个点一样,如果中途不一样,则返回false。否则结束后返回true。
3、计算第一个点和第二个点的斜率K,并分别计算剩下的点与第一个点的斜率
K
i
K_i
Ki并判断是否和K相等。如果中途不相等,则返回false,否则结束后返回true。
我的解决方案如下:
class Solution {
public:
bool checkStraightLine(vector<vector<int>>& coordinates) {
int len = coordinates.size();
if(len <= 2)
return true;
if(coordinates[0][0] == coordinates[1][0])//如果前两个数x相同,则判读后面的数x是否都和第一个相同
{
for(int i = 2;i < len;++i)
if(coordinates[i][0] != coordinates[0][0])
return false;
}
else
{
//计算两点的斜率,然后判断后面每个点和第一个点的斜率,如果出现不相同则false
float k = (coordinates[1][1] - coordinates[0][1]) * 1.0 / (coordinates[1][0] - coordinates[0][0]);
for(int i = 2;i < len;++i)
{
if((coordinates[i][1] - coordinates[0][1]) * 1.0 / (coordinates[i][0] - coordinates[0][0]) != k)
return false;
}
}
return true;
}
};
做完题目后我去看了一下题解,发现了一个很有意思的做法,可以避免算除法和除0的判断。实际上他只是做了一个很巧妙的变换,后面我们不再判断斜率是否相等,而是对斜率的式子做一个变形。比如我们原来判断的是 ( y 2 − y 1 ) / ( x 2 − x 1 ) = = ( y i − y 1 ) / ( x i − x 1 ) (y_2 - y_1)/(x_2 - x_1) ==(y_i - y_1)/(x_i - x_1) (y2−y1)/(x2−x1)==(yi−y1)/(xi−x1) ,现在对它交叉相乘,判断 ( y 2 − y 1 ) ∗ ( x i − x 1 ) = = ( y i − y 1 ) ∗ ( x 2 − x 1 ) (y_2 - y_1)*(x_i - x_1)==(y_i - y_1)*(x_2-x_1) (y2−y1)∗(xi−x1)==(yi−y1)∗(x2−x1).下面是改造过后的解决方案:
class Solution {
public:
bool checkStraightLine(vector<vector<int>>& coordinates) {
int len = coordinates.size();
if(len <= 2)
return true;
//为了避免除法和除零的判断,可以转变为乘法,乘法效率比除法高
int preDx = coordinates[1][0] - coordinates[0][0],preDy = coordinates[1][1] - coordinates[0][1],dx,dy;
for(int i = 2;i < len;++i)
{
dx = coordinates[i][0] - coordinates[0][0];
dy = coordinates[i][1] - coordinates[0][1];
if(dy * preDx != dx * preDy)
return false;
}
return true;
}
};
这一道题倒不是说后面的方法在效率上有多大提升,而是让我学会了思维的灵活转变,正着不行反着来,除法不行做个变换变成乘法,有时候做什么事也是如此,如果往一个方向一直得不到好的结果,不妨逆向思考一下,也许会有不一样的体会。
原题及链接:
在一个 XY 坐标系中有一些点,我们用数组 coordinates 来分别记录它们的坐标,其中 coordinates[i] = [x, y] 表示横坐标为 x、纵坐标为 y 的点。
请你来判断,这些点是否在该坐标系中属于同一条直线上,是则返回 true,否则请返回 false。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/check-if-it-is-a-straight-line
示例一:
输入: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 中不含重复的点