题目
- 给定一个二维平面,平面上有 n 个点,求最多有多少个点在同一条直线上。
示例
①示例1
![[LeetCode] 149.直线上最多的点数(Hard)C语言题解 [LeetCode] 149.直线上最多的点数(Hard)C语言题解](/default/index/img?u=L2RlZmF1bHQvaW5kZXgvaW1nP3U9YUhSMGNITTZMeTl3YVdGdWMyaGxiaTVqYjIwdmFXMWhaMlZ6THpjMk55OWpPRGxoTldVd1ptWTFPRFU1T1RSbFlUZGtaREF5TlRjek5tUTJZekZqWmk1d2JtYz0=)
②示例2
![[LeetCode] 149.直线上最多的点数(Hard)C语言题解 [LeetCode] 149.直线上最多的点数(Hard)C语言题解](/default/index/img?u=L2RlZmF1bHQvaW5kZXgvaW1nP3U9YUhSMGNITTZMeTl3YVdGdWMyaGxiaTVqYjIwdmFXMWhaMlZ6THpVeU1TOHdOamxqTlRGaFlqbGtZelkzWXpNelptRTFaVEl4TWpJMk1EUmhaVE00TVM1d2JtYz0=)
说明
①相关话题
②题目地址
解题方法
①暴力解法
- 由于三点确定一条直线,我们可以选取所有可能的两个点,然后从剩余的点中判断是否和选取的两个点在同一条直线上。
- 注意:不能用公式 (longint)(y1−y2)/(x1−x2)==(longint)(y3−y2)/(x3−x2) 比较,这样可能会出现除以0的情况,需要转换成 (longint)(y1−y2)∗(x3−x2)=(longint)(y3−y2)∗(x1−x2)。
- 时间复杂度: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;
}
附录