力扣算法题:最佳直线(算法小白每日一题)

题号:面试题16.14 最佳直线

题目内容:

        给定一个二维平面及平面上的 N 个点列表Points,其中第i个点的坐标为Points[i]=[Xi,Yi]。请找出一条直线,其通过的点的数目最多。

        设穿过最多点的直线所穿过的全部点编号从小到大排序的列表为S,你仅需返回[S[0],S[1]]作为答案,若有多条直线穿过了相同数量的点,则选择S[0]值较小的直线返回,S[0]相同则选择S[1]值较小的直线返回。

注:
  • 2 <= len(Points) <= 300
  • len(Points[i]) = 2
示例:
输入: [[0,0],[1,1],[1,0],[2,0]]
输出: [0,2]
解释: 所求直线穿过的3个点的编号为[0,2,3]

解题过程与思路(本题采用暴力循环方式和优化方式):

        题目要求一条穿过最多点的直线,对于给定起始点,可以利用剩余点与起始点连成的直线的斜率是否相等来进行判断,因为给定一点和斜率能唯一确定一条直线(点斜式)。

        具体实现过程:可以从给定点集的第一点开始(一层循环),遍历剩余的点(两层循环),先确定一条直线,再循环遍历所有点(三层循环),如果斜率相等,则加入结果集。遍历结束后,判断本次与上次结果集的长度,编号,决定保留还是丢弃。

使用python编写代码如下:

def best_line(points: List[List[int]]) -> List[int]:
    s = []
    for i in range(len(points) - 1):  # 只需要遍历到倒数第二个点即可
        for j in range(i + 1, len(points)):  # 选取剩下还没有当过起始点的点
            temp = []
            delta_x = points[j][0] - points[i][0]  # 计算横坐标差
            if delta_x == 0:  # 考虑斜率不存在的情况
                for index in range(len(points)):
                    if points[index][0] == points[i][0]:  # 横坐标相同,加入到列表中
                        temp.append(index)
            else:
                temp.append(i)  # 添加起始点
                k = (points[j][1] - points[i][1]) / delta_x  # 计算斜率
                for index in range(len(points)):
                    if points[index][0] == points[i][0]:  # 斜率不存在,跳过
                        continue
                    if k == (points[index][1] - points[i][1]) / (points[index][0] - points[i][0]):  # 斜率相同,加入到列表中
                        temp.append(index)

            temp.sort()  # 升序排序,便于比较编号
            if len(temp) > len(s):  # 对比列表长度
                s = temp
            if len(temp) == len(s):  # 对比编号
                if temp[0] < s[0] or (temp[0] == s[0] and temp[1] < s[1]):
                    s = temp

    return [s[0], s[1]]

        可以看到上述代码使用了三层循环,运行效率极慢,并且需要处理复杂的边界条件,显然不够优雅,让我们从头开始优化思路,具体优化过程:力扣算法题:最佳直线(优化)

关注我,从零开始的算法小白之路。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值