每天一刷,强迫学习
Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.
看到题目就懵了,多年不学数学的下场:输入一串带坐标的点,求二维平面中在一条直线上的最多的点的个数。
思路:
1、首先判断一个点是否在一条直线上的方法,从数学上来讲当然是计算y=kx+b的常量数字了,但是很明显k、b很有可能是浮点数,而浮点数计算判断相等在计算机中从来不是简单的事情。谢天谢地,题目中的坐标均为int类型,这样我们就可以利用三个点之间的向量是否两两平行来计算;
2、讨论三个点在一条直线上的方法:
a)其中两个点或三个点重合,例如输入为(1,1)(1,1)(2,2),此时三点必在一条直线上;
b)三个点均不重合,但是三个点之间的向量中某个坐标值均为0,比如(1,1)(2,1)(3,1),其中两个向量为(-1,0)(-2,0),如果两个向量横坐标方向或者纵坐标方向均为0,则此三点在一条直线上;
c)三个点均不重合,但是三个点之间的向量中某个坐标值为0,其他不为零,则三点必然不再一条直线上;
d)b、c两步的判断是因为向量为0时无法用x1/y1=x2/y2来计算,均不为零时可以转化为x1*y2==x2*y1来判断是否为真,为真则在一条直线上,否则不在一条直线上。
3、接下来就是用两个不同位置的点确认一条直线,两个for循环内判断两个点是否是同一个点,如果是则continue,不是则遍历剩余所有的点。遍历过程中如果判断是在同一条直线上则值+1;
4、从数组中选出点最多的那条线,将结果返回。
总结:
1、思路清晰比强写代码好的多;
2、如果想不出来,画画也是好的;
3、写代码过程中没有考虑两个点是同一个点的情况、输入只有一个点的情况、所有点都是一个点的情况,造成多次返工。
4、效率上有些问题,用来确定直线的两个点遍历到第三个点的时候,可以不再判断三个点与前两个点确定的直线的情况。如此一来效率提高,但代码较为复杂。实际生产中需考虑输入的规模,有必要就加以改进,规模不大也不必花太大的心思。
看着自己写的代码想起了微软的那个笑话:费劲心思偷窃出来windows最后几页源代码,发现全是}}}}}}}}}}}}}}}
/**
* Definition for a point.
* class Point {
* int x;
* int y;
* Point() { x = 0; y = 0; }
* Point(int a, int b) { x = a; y = b; }
* }
*/
public class Solution {
public boolean comp(Point a, Point b, Point c) {
if((a.x == b.x && a.y==b.y)||(c.x == b.x && c.y==b.y)||(a.x == c.x && a.y==c.y)){
return true;
}
int dirX1 = a.x - b.x;
int dirX2 = a.x - c.x;
int dirY1 = a.y - b.y;
int dirY2 = a.y - c.y;
if ((dirX1 == 0 && dirX2 == 0) || (dirY1 == 0 && dirY2 == 0)) {
return true;
} else if ((dirX1 == 0 && dirX2 != 0) || (dirX1 != 0 && dirX2 == 0)
|| (dirY1 == 0 && dirY2 != 0) || (dirY1 != 0 && dirY2 == 0)) {
return false;
} else {
int m1 = dirX1 * dirY2;
int m2 = dirX2 * dirY1;
if (m1 == m2)
return true;
else
return false;
}
}
public int maxPoints(Point[] points) {
int len = points.length;
int[][] sizeOneLine = new int[len][len];
for (int i = 0; i < len; i++) {
for (int j = 0; j < len; j++) {
sizeOneLine[i][j] = 2;
}
}
if (len == 2 || len == 1) {
return len;
}
boolean isOnePoint = true;
for(int i = 1; i < len; i++){
if(points[0].x != points[i].x || points[0].y != points[i].y ){
isOnePoint = false;
break;
}
}
if(isOnePoint){
return len;
}
for (int i = 0; i < len; i++) {
for (int j = 0; j < len; j++) {
if(points[i].x == points[j].x && points[i].y==points[j].y)
continue;
for (int m = 0; m < len; m++) {
if (i != j && i != m && j != m) {
if (comp(points[i], points[j], points[m])) {
sizeOneLine[i][j] += 1;
}
}
}
}
}
int temp = 0;
for(int i=0;i<len;i++){
for(int j=0;j<len;j++){
if(temp < sizeOneLine[i][j]){
temp = sizeOneLine[i][j];
}
}
}
return temp;
}
}