《LeetCode之每日一题》:69.直线上最多的点数
Posted 是七喜呀!
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《LeetCode之每日一题》:69.直线上最多的点数相关的知识,希望对你有一定的参考价值。
题目链接: 直线上最多的点数
有关题目
给你一个数组 points ,其中 points[i] = [xi, yi] 表示 X-Y 平面上的一个点。
求最多有多少个点在同一条直线上。
提示:
1 <= points.length <= 300
points[i].length == 2
-10^4 <= xi, yi <= 10^4
points 中的所有点 互不相同
题解
法一:哈希表
思路:
统计其他所有点与点 i 所连直线的斜率
出现次数最多的斜率即为经过点数最多的直线的斜率,存放在ret中
struct HashTable
{
int key,val;
UT_hash_handle hh;
};
//递归实现求解最大公约数,去除1 / 2 = 2 / 4斜率重合现象
int gcd(int a,int b)
{
return b ? gcd (b, a % b) : a;
}
int maxPoints(int** points, int pointsSize, int* pointsColSize){
int n = pointsSize;
//特判
if (n <= 2)
return n;
int ret = 0;//存放最大值
for (int i = 0; i < n; i++)
{
//①
//对点i来说,至多只能找到n - i个点共线,若满足之前找到的ret >= n - i,则最大值肯定
//无法出现i之后的点中了,直接拿到答案
//②
//当我们找到一条直线经过了图中超过半数的点时,我们即可以确定该直线即为经过最多点的直线
//直接拿到答案
if (ret >= n - i || ret > n / 2)
return ret;
struct HashTable* hashtable = NULL;
for (int j = i + 1; j < n; j++)
{
//浮点数类型可能因为精度不够而无法足够精确地表示每一个斜率
//因此我们将斜率 = (y增量) / (x增量)用分子和分母组成的二元组来代表斜率,即(my,mx)
int x = points[i][0] - points[j][0];//x增量
int y = points[i][1] - points[j][1];//y增量
//我们对于x和y为零时的特殊情况进行特判
//同时我们保证y增量为正,若遇到斜率为负的情况,我们对二元组中两个数同时取相反数
if (x == 0)
y = 1;
else if (y == 0)
x = 1;
else
{
if (y < 0)
{
x = -x;
y = -y;
}
int gcdXY = gcd(abs(x),abs(y));
x /= gcdXY, y /= gcdXY;
}
//创建哈希表存放,斜率和对应出现次数
struct HashTable* tmp;
//结合横纵坐标的范围-10^4 <= xi, yi <= 10^4
//我们利用构造一个法则val = y + 20001 * x通过一个整形int来表示x和y这两个整数即用来表示斜率
int val = y + 20001 * x;
HASH_FIND_INT(hashtable,&val,tmp);
if (tmp == NULL)
{
tmp = (struct HashTable*)malloc(sizeof(struct HashTable));
tmp->key = val;//上方的创建法则表示的斜率值
tmp->val = 1;//对于斜率出现一次
HASH_ADD_INT(hashtable,key,tmp);
}
else
tmp->val++;
}
//找出哈希表中的对应斜率key出现最多的次数val
int maxn = 0;
struct HashTable *iter, *tmp;
HASH_ITER(hh,hashtable,iter,tmp){
maxn = fmax(maxn,iter->val + 1);
HASH_DEL(hashtable,iter);
free(iter);
}
ret = fmax(maxn,ret);
}
return ret;
}
C++
class Solution {
public:
//递归实现求解最大公约数,去除1 / 2 = 2 / 4斜率重合现象
int gcd(int a,int b)
{
return b ? gcd (b, a % b) : a;
}
int maxPoints(vector<vector<int>>& points) {
int n = points.size();
//特判
if (n <= 2)
return n;
int ret = 0;//存放最大值
for (int i = 0; i < n; i++)
{
if (ret >= n - i || ret > n / 2)
return ret;
unordered_map<int,int> mp;
for (int j = i + 1; j < n; j++)
{
int x = points[i][0] - points[j][0];//x增量
int y = points[i][1] - points[j][1];//y增量
if (x == 0)
y = 1;
else if (y == 0)
x = 1;
else
{
if (y < 0)
{
x = -x;
y = -y;
}
int gcdXY = gcd(abs(x),abs(y));
x /= gcdXY, y /= gcdXY;
}
mp[y + 20001 * x]++;
}
int maxn = 0;
for (auto& [_,num] : mp)
{
maxn = max(maxn,num + 1);
}
ret = max(ret,maxn);
}
return ret;
}
};
以上是关于《LeetCode之每日一题》:69.直线上最多的点数的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode第149题—直线上最多的点数—Python实现