欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【Leetcode】149. Max Points on a Line 149. 直线上最多的点数

程序员文章站 2022-07-15 12:43:15
...

【Leetcode】149. Max Points on a Line 149. 直线上最多的点数

解法

太多坑了这题
只能依次记录每条直线上的点
需要解决的问题就是:

如何唯一地标识一条直线?

用三元组(A,B,C),要注意2点,一是最简约分,二是统一正负号。比如我就统一为第一个非0的数为正

另外还有一个坑:

如何处理重复点?

首先,重复点不能作为得到直线的两个端点
其次,重复点的重复次数也是答案的候选者之一

# Definition for a point.
# class Point(object):
#     def __init__(self, a=0, b=0):
#         self.x = a
#         self.y = b

class Solution(object):
    def maxPoints(self, points):
        """
        :type points: List[Point]
        :rtype: int
        """
        def simplify(a,b,c):
            # print 'before:',a,b,c
            d = 2
            m = min(map(abs,filter(lambda x:x,(a,b,c))) or [-1])
            if m==-1:
                return a,b,c
            while d*d<=m:
                if m%d==0:
                    while a%d==0 and b%d==0 and c%d==0:
                        a,b,c = a/d,b/d,c/d
                        m /= d
                    while m%d==0:
                        m/=d
                d += 1
            if m>1:
                while a%m==0 and b%m==0 and c%m==0:
                        a,b,c = a/m,b/m,c/m
            # print 'after',a,b,c
            return a,b,c
            
        def ABC(a,b):
            x = b[0]-a[0]
            y = b[1]-a[1]
            i,j,k = y,-x,a[1]*x-y*a[0]
            if i<0 or (i==0 and j<0) or (i==0 and j==0 and k<0):
                i,j,k = -i,-j,-k
            return i,j,k
        from collections import defaultdict
        cnt = defaultdict(set)
        for i,p in enumerate(points):
            cnt[(p.x,p.y)].add(i)
        n = len(cnt)
        if n<=2:
            return len(points)
        ans = defaultdict(set)
        for i,j in itertools.combinations(cnt.keys(),2):
            line = simplify(*ABC(i,j))
            ans[line] |= cnt[i] | cnt[j]
        return max(map(len,ans.values()+cnt.values()))