本题的最简单的方法暴力解三层循环
题目链接:直线上最多的点数Hard
那么复杂度就是
O
(
n
3
)
O(n^3)
O(n3),按照题目中的点数范围,最大我们需要计算
1
0
6
10^6
106的量级。
哈希表 + 两次遍历
下面给出该方法的计算过程:
- 首先枚举两点之间确定的直线斜率和截距,并通过转化为字符串进行保存,作为key放入到字典中,经过两层循环我,那我我们便可以得到每一条直线下共有多少对点,满足这条直线的斜率和截距,复杂度 O ( n 2 ) O(n^2) O(n2)。
- 之后我们便可以通过一次遍历的方法得到字典中那一条直线所含的点对最多。便可以通过解方程得到。
- 如何计算:
比如说一共有三个点存在一条直线上,那么我们通过两层遍历便可以得到一共有
n
(
n
−
1
)
/
2
=
3
∗
2
/
2
=
3
n(n-1)/2 = 3*2/2 = 3
n(n−1)/2=3∗2/2=3的点对。有这个方程之后假设最大的点对为
x
x
x。那么有下面的方法求解n:
n
(
n
−
1
)
/
2
=
x
n
2
−
n
+
1
4
=
2
x
+
1
4
(
n
−
1
2
)
2
=
2
x
+
1
4
n
=
2
x
+
1
4
+
1
2
n(n-1)/2 = x \\ n^2 - n + \frac{1}{4} = 2x + \frac{1}{4} \\ (n - \frac{1}{2})^2 = 2x + \frac{1}{4} \\ n = \sqrt{2x + \frac{1}{4}} + \frac{1}{2}
n(n−1)/2=xn2−n+41=2x+41(n−21)2=2x+41n=2x+41+21
- 关于截距和斜率的保存方式:
由于 w = d y d x , 而 1 ≤ ∣ d y ∣ , ∣ d x ∣ ≤ 1 0 4 w = \frac{d_y}{d_x}, \text{而}1 \le |d_y|, |d_x| \le 10^4 w=dxdy,而1≤∣dy∣,∣dx∣≤104,所以 w w w的最小间隔为 0.00005 0.00005 0.00005,所以我们在转化为 str \text{str} str的时候只包含小数点的前5位便可以,保留过多和过少分别会导致同一条直线分为多条直线,以及多条直线成为一条直线。
代码:
class Solution:
def maxPoints(self, points: List[List[int]]) -> int:
rate = collections.defaultdict(int)
for i in range(len(points)):
for j in range(i+1, len(points)):
if points[i][0] == points[j][0]: #竖线
rate["inf" + "<>" + str(points[i][0])] += 1
elif points[i][1] == points[j][1]: #横线
rate["0<>" + str(points[i][1])] += 1
else: #普通线
d_x = points[i][0] - points[j][0]
d_y = points[i][1] - points[j][1]
w = d_y / d_x
b = points[i][1] - w * points[i][0]
rate[f'{w:.5f}' + "<>" + f"{b:.5f}"] += 1
max_cnt = 0
for key in rate.keys():
if rate[key] > max_cnt:
max_cnt = max(max_cnt, rate[key])
return int(sqrt(2 * max_cnt + 0.25) + 0.5)