【力扣python】149. 直线上最多的点数

这篇博客介绍了两种解决最多点共线问题的算法。第一种算法通过使用k和b作为直线唯一标识,处理特殊情况如垂直线。第二种算法采用剪枝策略,利用最大公约数简化斜率,并避免重复计算。这两种方法都有效地找出直线上最多的点数。
摘要由CSDN通过智能技术生成

149. 直线上最多的点数

在这里插入图片描述

解法目录

写法一

自己的解,需要注意的点是:
(1)使用k和b来作为唯一标识
(2)当直线为垂直时,b为None,斜率k需要加入x轴位置来作为唯一标识

class Solution:
    def maxPoints(self, points) -> int:
        pointsNum = len(points)
        de = defaultdict(list)
        for i in range(pointsNum):
            for j in range(i+1, pointsNum):
                deltaX = points[i][0] - points[j][0]
                k = (points[i][1] - points[j][1])/deltaX if deltaX != 0 else f"{float('inf')}{points[j][0]}"
                b = points[i][1] - k*points[i][0] if type(k) != str else None
                if str(points[i]) not in de[(k, b)]:
                    de[(k, b)].append(str(points[i]))
                if str(points[j]) not in de[(k, b)]:
                    de[(k, b)].append(str(points[j]))
        max_ = 1
        for per in de:
            max_ = max(len(de[per]), max_)
        return max_	

写法二

官方方法,利用了一定的剪枝

class Solution:
    def gcd(self, a, b):
        return self.gcd(b, a % b) if b else a # 直到b为0就返回a,即最大公约数

    def maxPoints(self, points) -> int:
        n = len(points)
        if n <= 2: # 当点少于等于2(剪枝一)
            return n # 直接返回,必定同一直线
        ret = 0 # 记录最大可能的在同一直线的点数
        for i in range(n):
            # 当之前的最多点都已经大于剩下的点,或过半了,则不用再查了(剪枝三,剪枝四)
            if ret >= n - i or ret > n / 2: 
                break
            mp = defaultdict(int) # 只需要保存i及之后的点的斜率,从而避免斜率同b不同的情况(剪枝二)
            for j in range(i + 1, n):
                x, y = points[i][0] - points[j][0], points[i][1] - points[j][1]
                if x == 0:
                    y = 1
                elif y == 0:
                    x = 1
                else:
                    x, y = (-x, -y) if y < 0 else (x, y)
                    gcdXY = self.gcd(abs(x), abs(y))
                    x /= gcdXY
                    y /= gcdXY
                
                mp[y + x * 20001] += 1 # 保证每个斜率k映射到的值不同, 比如1/2 和 2/1, 直接加起来都是3
            ret = max(ret, max([mp[per] + 1 for per in mp]))
        return ret
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值