leetcode 149 直线上最多的点

一道让人难以发力,难以下手的题目。看了题解之后觉得思路并不困难。遍历所有点,对某一点而言,计算其到所有另外点的斜率,其中最多的斜率,就是过这一点的点最多的某条直线的斜率。通过这个思路去遍历所有点就能得到结果。而有几个优化的方面,一个是对于每个点,只需要计算该节点与该节点后面的点的斜率,因为如果对于j计算其与i之间的斜率,这一直线已经在对i遍历的时候计算过了,所以不需要重新计算。第二点是斜率的保存方式,该例中使用二元组的方式保存斜率,并且通过计算最大公约数的方式进行约分,若上下分别为0则有特殊的操作,这样以来就能够保证斜率的正确性。第三点,如果当前存储的结果大于n的一半或者大于剩余未遍历的节点,则可以提前返回,因为在这两种情况下,经过剩下的点的直线经过的点都无法比当前结果更多,所以可以提前结束。贴代码

 1 class Solution {
 2 public:
 3     int gcd(int a,int b)
 4     {
 5         return b?gcd(b,a%b):a;
 6     }
 7     int maxPoints(vector<vector<int>>& points) 
 8     {
 9         int n = points.size();
10         if(n<=2)
11         return n;
12         int ret = 0;
13         for(int i = 0 ; i < n ; i++)
14         {
15             if(ret>n-i || ret>n/2)
16             return ret;
17             unordered_map<int,int> mp;
18             for(int j = i+1 ; j < n ; j++)
19             {
20             int x = points[i][0]-points[j][0];
21             int y = points[i][1]-points[j][1];
22             if(x == 0)
23             y = 1;
24             else if(y == 0)
25             x = 1;
26             else 
27             {
28                 if(y<0)
29                 {
30                     x = -1*x;
31                     y = -1*y;
32                 }
33                 int gcdXY = gcd(abs(x),abs(y));
34                 x/=gcdXY;
35                 y/=gcdXY;
36             }
37             mp[y+x*20001]++;
38             }
39             int maxn = 0;
40             for(auto& [_,num]:mp)
41             maxn = max(maxn,num+1);
42             ret = max(ret,maxn);
43         }
44         return ret;
45     }
46 };

 

posted @ 2021-11-16 20:12  zhaohhhh  阅读(57)  评论(0)    收藏  举报