问题来源

atan2函数
在做之前,先解释一下C语言math.h库中的atan2函数,他的作用就是求出以弧度表示的一个点相对与原点的反正切值,取值范围为:
(
−
π
,
π
]
(-\pi,\pi]
(−π,π],不包括
−
π
-\pi
−π
double atan2(double y, double x)
在此基础上,对参数动一下手脚,就可以得到任意的两个点之间以弧度表示的反正切值
r
e
s
=
y
−
0
x
−
0
res=\frac{y - 0}{x-0}
res=x−0y−0
⇒
r
e
s
=
y
x
\Rightarrow res=\frac{y}{x}
⇒res=xy
弧度的计算公式为: 角 度 数 × ( π / 180 ° ) 角度数\times(π /180°) 角度数×(π/180°)
那么,如果我们想求出任意两个点的弧度,在传参的过程中,传入相对于一个点偏移就可以了
atan2(y1 - y,x1 - x);
那么,所求的结果为 ( x 1 , y 1 ) (x1,y1) (x1,y1)点相对于 ( x , y ) (x,y) (x,y)点的弧度的反正切值
根据弧度求角度
将 a t a n 2 ( ) atan2() atan2()函数的返回值, × 180 / π \times 180/\pi ×180/π,这里的 π \pi π可以使用我们自定义的宏来代替,以前经常背诵的圆周率用上了。。。
#define PI 3.1415926535

未通过的解法
很遗憾,leetcode在最后的结果中卡了库函数的精度,所以使用atan2()库函数求解是不对的
- [[0,0],[94911150,94911151],[94911151,94911152]]
- [[0,0],[94911151,94911150],[94911152,94911151]]
打表的两个用例,大家乐呵一下就可以了
class Solution {
public:
int maxPoints(vector<vector<int>>& points) {
int n = points.size();
if(n < 2) return n;
//if(n == 3 && points[0][0] == 0 && points[1][0] == 94911150 && points[2][0] == 94911151) return 2;
//if(n == 3 && points[0][0] == 0 && points[1][0] == 94911151 && points[2][0] == 94911152) return 2;
int res = 0;
for(int j = 0; j < n; j++) {
#define PI 3.1415926535
unordered_map<double,int> mp;
int same = 1; // 相同点的数量
for(int i = 0; i < n; i++) {
if(i == j) continue;
if(points[i][1] == points[j][1] && points[i][0] == points[j][0]) {
same++;
continue;
}
double t = atan2(points[i][1] - points[j][1],points[i][0] - points[j][0]);
t = t + 360;
//cout << t << " ";
mp[t]++;
}
//cout << same << "-";
//puts("");
for(auto& e : mp) {
int x = e.first, y = e.second;
if(mp.count(x + 180)) y += mp[x+180];
res = max(res,y + same);
//cout << res << " ";
}
//puts("");
res = max(res,same);
}
return res;
}
};
ac程序
程序使用斜率来进行解决,但是首先要统计每个点出现的次数,因为会出现重复的点
注意,统计点出现的次数时,不可使用
unordered_map哈希表

可以看出,报出的错误时,unordered_map隐式的删除了默认构造函数。

因为我们所传入的第一个键值key的类型是一个pair<int,int>类型,在初始化的时候,不能得到一个unordered_map的实例,因为pair<int,int>没有默认构造函数,在实例化pair的对象时,一定要存在初值,所以使用unordered_map会报错

另外,如果我们非得使用哈希表的话,可以考虑自定义一个pair,然后重写默认构造函数,让unordered_map可以无参进行实例化就可
class Solution {
public:
typedef pair<int,int> PII;
typedef long long LL;
int maxPoints(vector<vector<int>>& points) {
int n = points.size();
if(n < 2) return n;
map<PII,int> mp; // 统计每个点出现的次数
for(auto& e : points) mp[{e[0],e[1]}] ++;
vector<pair<PII,int> > vec; // 记录每个点出现的次数
for(auto& e : mp) vec.push_back(e);
n = vec.size();
if(n == 1) return vec[0].second; // 排除只存在一个点的情况
int res = 0;
for(int i = 0; i < n; i++)
for(int j = i + 1; j < n; j++) {
// 记录 i j 的斜率
LL x = vec[j].first.first - vec[i].first.first;
LL y = vec[j].first.second - vec[i].first.second;
int cur = vec[i].second + vec[j].second; // 当前直线中点的数量
// 统计后面的点
for(int k = j + 1; k < n; k++) {
LL tx = vec[k].first.first - vec[i].first.first;
LL ty = vec[k].first.second - vec[i].first.second;
if(tx * y == ty * x) cur += vec[k].second;
}
res = max(res,cur);
}
return res;
}
};
1万+

被折叠的 条评论
为什么被折叠?



