题目
给定一个二维平面,平面上有 n 个点,求最多有多少个点在同一条直线上。
示例
①示例1
②示例2
说明
①相关话题
②题目地址
解题方法
①暴力解法
由于三点确定一条直线,我们可以选取所有可能的两个点,然后从剩余的点中判断是否和选取的两个点在同一条直线上。 注意:不能用公式
(
l
o
n
g
i
n
t
)
(
y
1
−
y
2
)
/
(
x
1
−
x
2
)
=
=
(
l
o
n
g
i
n
t
)
(
y
3
−
y
2
)
/
(
x
3
−
x
2
)
(long int)(y1-y2) / (x1-x2) == (long int)(y3-y2) / (x3-x2)
( l o n g i n t ) ( y 1 − y 2 ) / ( x 1 − x 2 ) = = ( l o n g i n t ) ( y 3 − y 2 ) / ( x 3 − x 2 ) 比较,这样可能会出现除以0的情况,需要转换成
(
l
o
n
g
i
n
t
)
(
y
1
−
y
2
)
∗
(
x
3
−
x
2
)
=
(
l
o
n
g
i
n
t
)
(
y
3
−
y
2
)
∗
(
x
1
−
x
2
)
(long int)(y1-y2) * (x3-x2) = (long int)(y3-y2) * (x1-x2)
( l o n g i n t ) ( y 1 − y 2 ) ∗ ( x 3 − x 2 ) = ( l o n g i n t ) ( y 3 − y 2 ) ∗ ( x 1 − x 2 ) 。 时间复杂度:O(N^3)。 空间复杂度:O(1)。
②数学 + 哈希表
因为键值不是整数,所以这里的哈希表使用 uthash 。 uthash 是一个用 C 语言编写的开源库,使用宏实现了哈希表的增删改查等功能。 因为两点可以确定一条直线,且斜率相同的点在同一条直线上。所以我们可以选择每次固定一个点,求固定点与其他点的斜率,即哈希表的键值为此斜率,同时记录斜率相同的点的个数,每次通过哈希表找出其最大值,就可以得出与固定点有关的直线上的最多点数。 而两点间的斜率值类型为浮点型,不能做 uthash 的键值,所以先要把浮点数转化为字符串,然后用字符串做键值。 注意重复点、斜率不存在的点都要额外处理。 时间复杂度:O(N^2)。 空间复杂度:O(N)。
代码详解
int maxPoints ( struct Point* points, int pointsSize) {
if ( pointsSize < 3 )
return pointsSize;
int max = 0 ;
for ( int i = 0 ; i < pointsSize; i++ ) {
for ( int j = i+ 1 ; j < pointsSize; j++ ) {
int count = 2 ;
for ( int k = 0 ; k < pointsSize; k++ ) {
if ( k != i && k != j) {
int x1 = points[ i] . x, y1 = points[ i] . y, x2 = points[ j] . x, y2 = points[ j] . y, x3 = points[ k] . x, y3 = points[ k] . y;
if ( x1 == x2 && x3 == x1)
count++ ;
else if ( x1 != x2 && ( long int ) ( y3- y2) * ( x2- x1) == ( long int ) ( y2- y1) * ( x3- x2) )
count++ ;
}
}
max = max > count? max: count;
}
}
return max;
}
int maxPoints ( struct Point* points, int pointsSize) {
struct hash {
char key[ 30 ] ;
int count;
UT_hash_handle hh;
} ;
int max = 0 ;
for ( int i = 0 ; i < pointsSize; i++ ) {
struct hash * hashTable = NULL ;
int c1 = 0 , c2 = 1 ;
for ( int j = 0 ; j < pointsSize; j++ ) {
int m = points[ i] . x- points[ j] . x, n = points[ i] . y- points[ j] . y;
if ( j != i) {
if ( points[ i] . x == points[ j] . x && points[ i] . y == points[ j] . y)
c1++ ;
else if ( m != 0 ) {
struct hash * h;
double k = n == 0 ? 0.0 : ( double ) m / n;
char s[ 30 ] ;
sprintf ( s, "%.20f" , k) ;
HASH_FIND_STR ( hashTable, s, h) ;
if ( h)
h- > count++ ;
else {
h = malloc ( sizeof ( struct hash) ) ;
strcpy ( h- > key, s) ;
h- > count = 2 ;
HASH_ADD_STR ( hashTable, key, h) ;
}
}
else
c2++ ;
}
}
if ( hashTable) {
for ( struct hash * s = hashTable; s!= NULL ; s = s- > hh. next)
c2 = s- > count > c2? s- > count: c2;
}
max = c1+ c2 > max? c1+ c2: max;
}
return pointsSize == 0 ? 0 : max;
}
附录