Solutions to high-frequency interview questions of LeetCode in C++17, taking into account both efficiency and comprehensibility.
经过 (x1, y1)、(x2, y2) 的两点式方程为
(x - x1) / (x2 - x1) = (y - y1) / (y2 - y1)
分子#分母
的字符串来存储斜率。为了保证相同斜率的字符串相同,应对分子分母约分。水平线斜率应表示为 0#1
,垂直线斜率应表示为 1#0
,如果斜率为负数则负号在前,如 -1#1
string getK(int x, int y) {
int a = x;
int b = y;
while (b) { // 辗转相除法
int t = a % b;
a = b;
b = t;
} // a 即为 x 与 y 的最大公约数,任何数与 0 的最大公约数为本身
x /= a;
y /= a;
return to_string(x) + "#" + to_string(y);
}
// x = 2 y = 1 => "2#1"
// x = 4 y = 2 => "2#1"
// x = 3 y = 0 => "1#0"
// x = 1 y = 2 => "1#2"
// x = 0 y = 3 => "0#1"
// x = 1 y = -1 => "-1#1"
// x = -1 y = 1 => "-1#1"
// x = -1 y = -2 => "1#2"
// x = -3 y = 0 => "1#0"
// x = 0 y = -3 => "0#1"
class Solution {
public:
int maxPoints(vector<vector<int>>& points) {
int sz = size(points);
if (sz < 3) {
return sz;
}
int res = 0;
for (int i = 0; i < sz; ++i) {
int cnt = 0; // 与 points[i] 重合的点数量(不含 points[i] 自身)
int mx = 0; // 经过 points[i] 的所有直线中,经过最多的点数量
unordered_map<string, int> m; // 斜率为 k 的直线,经过点数量为 m[k]
for (int j = i + 1; j < sz; ++j) { // points[i] 与 points[j] 连成的直线
int dx = points[j][0] - points[i][0];
int dy = points[j][1] - points[i][1];
if (dx == 0 && dy == 0) { // 重合点
++cnt;
} else {
string k = getK(dx, dy);
++m[k];
mx = max(mx, m[k]);
}
}
res = max(res, mx + cnt + 1); // 最大点数 + 重合点数 + 自身
}
return res;
}
private:
string getK(int x, int y) {
int a = x;
int b = y;
while (b) {
int t = a % b;
a = b;
b = t;
}
x /= a;
y /= a;
return to_string(x) + "#" + to_string(y);
}
};