LeetCode----149. 直线上最多的点数

news2024/10/5 20:28:51

 题目

给你一个数组 points ,其中 points[i] = [ x i x_i xi, y i y_i yi] 表示 X-Y 平面上的一个点。求最多有多少个点在同一条直线上。

示例 1:
在这里插入图片描述

输入:points = [[1,1],[2,2],[3,3]]
输出:3

示例 2:
在这里插入图片描述

输入:points = [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]]
输出:4

提示:
1 <= points.length <= 300
points[i].length == 2
-104 <= xi, yi <= 1 0 4 10^4 104
points 中的所有点 互不相同

 解

解决这个问题的常用方法是使用哈希表。对于给定的点 ( x i x_i xi, y i y_i yi),我们可以计算其与其他点的斜率 ( x j x_j xj - x i x_i xi) / ( y j y_j yj - y i y_i yi),并将这个斜率存储在哈希表中。

具体步骤如下:

  1. 遍历每一个点 ( x i x_i xi, y i y_i yi),对于每个点,初始化一个哈希表 slopeMap,用于存储以该点为起点的直线上的点数。
  2. 然后再次遍历每一个点 ( x j x_j xj, y j y_j yj)(这个循环将计算所有点与点 ( x i x_i xi, y i y_i yi) 的斜率),如果 ( x j x_j xj, y j y_j yj) 与 ( x i x_i xi, y i y_i yi) 重合,将 overlap 值加 1,否则计算斜率 ( x j x_j xj - x i x_i xi) / ( y j y_j yj - y i y_i yi)。
  3. 将计算得到的斜率存储在 slopeMap 中,如果已存在该斜率,直线上的点数加 1,如果不存在,则初始化为 2(包括 ( x i x_i xi, y i y_i yi) 和 ( x j x_j xj, y j y_j yj))。
  4. 在每次内循环结束后,更新 maxPoints,确保始终保持记录最多点的直线上的点数。
  5. 继续遍历下一个点 ( x i x_i xi, y i y_i yi),并重复上述过程,直到所有点都被处理。

以下是Java代码示例:

class Solution {
    public int maxPoints(int[][] points) {
        if (points.length < 3) {
            return points.length;
        }

        int maxPoints = 2; // 初始化最大点数为2,因为至少有两个点在同一直线上

        for (int i = 0; i < points.length; i++) {
            int overlap = 0; // 用于记录与当前点重合的点数
            HashMap<Double, Integer> slopeMap = new HashMap<>(); // 用于存储斜率与点数的映射

            for (int j = 0; j < points.length; j++) {
                if (i == j) {
                    overlap++; // 与自身重合的点数加1
                } else {
                    double slope;
                    if (points[i][0] == points[j][0]) {
                        slope = Double.POSITIVE_INFINITY; // 当x坐标相同时,斜率设为正无穷大
                    } else {
                        slope = (double)(points[i][1] - points[j][1]) / (points[i][0] - points[j][0]); // 计算斜率
                    }
                    slopeMap.put(slope, slopeMap.getOrDefault(slope, 0) + 1); // 存储斜率并更新点数
                }
            }

            int localMax = overlap; // 初始化局部最大点数为与自身重合的点数
            for (int count : slopeMap.values()) {
                localMax = Math.max(localMax, count + overlap); // 更新局部最大点数
            }

            maxPoints = Math.max(maxPoints, localMax); // 更新全局最大点数
        }

        return maxPoints;
    }
}

这段代码通过哈希表来统计每个点的斜率,然后记录直线上的点数,最终找到直线上点数最多的情况。

 解2

除了上述的哈希表解法外,还有一种更优化的解法,可以在O(n^2)的时间内解决问题,其中n是点的数量。

这个解法基于以下观察:如果有三个点共线,那么它们的斜率是相同的。因此,我们可以遍历每一对点,计算它们之间的斜率,并存储在哈希表中。对于每个点,我们统计共线的点的数量,并保持更新最大值。

以下是基于这种观察的Java代码:

class Solution {
    public int maxPoints(int[][] points) {
        if (points.length < 3) {
            return points.length;
        }

        int maxPoints = 2; // 初始化最大点数为2,因为至少有两个点在同一直线上

        for (int i = 0; i < points.length; i++) {
            int overlap = 0; // 用于记录与当前点重合的点数
            HashMap<String, Integer> slopeMap = new HashMap<>(); // 用于存储斜率与点数的映射

            for (int j = 0; j < points.length; j++) {
                if (i == j) {
                    overlap++; // 与自身重合的点数加1
                } else {
                    int deltaX = points[i][0] - points[j][0];
                    int deltaY = points[i][1] - points[j][1];

                    if (deltaX == 0) {
                        slopeMap.put("inf", slopeMap.getOrDefault("inf", 0) + 1); // 斜率为正无穷
                    } else {
                        int gcd = gcd(deltaX, deltaY);
                        String slope = (deltaY / gcd) + "/" + (deltaX / gcd); // 用字符串表示斜率
                        slopeMap.put(slope, slopeMap.getOrDefault(slope, 0) + 1);
                    }
                }
            }

            int localMax = overlap; // 初始化局部最大点数为与自身重合的点数
            for (int count : slopeMap.values()) {
                localMax = Math.max(localMax, count + overlap); // 更新局部最大点数
            }

            maxPoints = Math.max(maxPoints, localMax); // 更新全局最大点数
        }

        return maxPoints;
    }

    // 辗转相除法计算最大公约数
    private int gcd(int a, int b) {
        return b == 0 ? a : gcd(b, a % b);
    }
}

这种解法避免了使用浮点数斜率,使用最大公约数来保持斜率的精度,同时也处理了斜率为正无穷的情况。这个解法的时间复杂度为O(n^2),但在实际应用中通常更高效。

 解3

动态规划的思路是,对于每个点 (xi, yi),可以考虑以它为终点的直线上的点数,然后记录最大值。下面是一个使用动态规划的Java代码示例:

class Solution {
    public int maxPoints(int[][] points) {
        if (points.length < 3) {
            return points.length;
        }

        int maxPoints = 2; // 初始化最大点数为2,因为至少有两个点在同一直线上
        int n = points.length;

        for (int i = 0; i < n; i++) {
            int overlap = 0; // 用于记录与当前点重合的点数
            int localMax = 0; // 用于记录以当前点为终点的直线上的点数
            HashMap<String, Integer> slopeMap = new HashMap<>(); // 用于存储斜率与点数的映射

            for (int j = i + 1; j < n; j++) {
                int deltaX = points[i][0] - points[j][0];
                int deltaY = points[i][1] - points[j][1];

                if (deltaX == 0 && deltaY == 0) {
                    overlap++; // 与自身重合的点数加1
                } else {
                    int gcd = gcd(deltaX, deltaY);
                    String slope = (deltaY / gcd) + "/" + (deltaX / gcd); // 用字符串表示斜率
                    slopeMap.put(slope, slopeMap.getOrDefault(slope, 0) + 1); // 存储斜率并更新点数
                    localMax = Math.max(localMax, slopeMap.get(slope)); // 更新以当前点为终点的直线上的点数
                }
            }

            maxPoints = Math.max(maxPoints, localMax + overlap + 1); // 更新全局最大点数,加1是因为还包括自身点
        }

        return maxPoints;
    }

    // 辗转相除法计算最大公约数
    private int gcd(int a, int b) {
        return b == 0 ? a : gcd(b, a % b);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1184597.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【通信原理】第三章 随机过程——例题

一、随机过程 1. 数学特征 ① 随机信号&#xff08;三角函数表达式&#xff09; ② 随机信号&#xff08;求和表达式&#xff09; 2. 功率谱密度 ① 相位确定&#xff0c;求功率谱密度 ② 已知相位分布&#xff0c;求功率谱密度 ③ 信号为两信号之和&#xff0c;求功率谱密度…

闲置电脑做什么副业赚钱?盘点如何利用电脑赚钱的方法

对于很多人来说&#xff0c;手机的强大功能使闲置的电脑被遗忘在角落。虽然现在手机已经取代电脑的很多用途。但是实际上&#xff0c;网络上还是有很多项目是手机不能展开的&#xff0c;而电脑方方面面都可以&#xff0c;所以&#xff0c;只要你愿意花些时间和精力&#xff0c;…

ConcurrentHashMap 源码解析

目录 一. 前言 二. 源码解析 2.1. 类结构 2.2. 基本属性 2.3. 构造方法 2.4. 增加元素 2.4.1. initTable() 2.4.2. helpTransfer() 2.4.3. transfer() 2.4.4. treeifyBin() 2.4.5. addCount() 2.5. 获取元素 2.6. remove() & replace() 2.7. clear() 2.8. s…

研发管理和项目管理有哪些痛点

研发管理和项目管理有哪些痛点 研发管理和项目管理有&#xff1a;1.项目进度把控难&#xff1b;2.绩效考核难&#xff1b;3.部门信息不同步&#xff1b;4.人力资源不均衡&#xff1b;5.需求管理难。项目进度把控难是研发管理和项目管理中的名列前茅痛点&#xff0c;要解决该问题…

引用类型;强引用;软引用;弱引用和虚引用

概述 平时在编写代码的时候内存都是由jvm管理&#xff0c;对象的回收也是jvm在管理&#xff1b; 但是有些时候jvm无法回收对象&#xff0c;最后就会抛出oom异常. 那么那些回收不了的对象肯定有区别于能回收的对象&#xff1b; 先上一波引用类型介绍 强引用 比如平常我们直…

Go进阶之rpc和grpc

文章目录 Go环境安装1&#xff09;windows2&#xff09;linux go语言编码规范1.1 包名&#xff1a;package1.2 ⽂件名1.3 结构体命名1.4 接⼝命名1.5 变量命名1.6 常量命名2.1 包注释2.2 结构&#xff08;接⼝&#xff09;注释2.3 函数&#xff08;⽅法&#xff09;注释2.4 代码…

三维变换与投影-计算机图形学

目录 三维变换与投影 三维变换原理 为什么C语言头文件要专门放在一个.h文件中呢&#xff1f; 斜投影原理 介绍一下什么是UGC 入口 透视投影 透视投影坐标系 三维变换与投影 三维变换原理 如何把三维物体投影到两维物体上 齐次坐标 加上一维&#xff0c;方便运算 …

chatGPT培训老师AIGC培训讲师叶梓:大模型这么火,我们在使用时应该关注些什么?-6

以下为叶老师讲义分享&#xff1a; P25-P29 提示工程的模式 节省计算资源&#xff1a; 在微调过程中&#xff0c;不需要重新训练整个模型&#xff0c;因此可以节省计算资源。 提高特定任务上的性能&#xff1a; 通过微调&#xff0c;模型可以适应特定任务的语言特征和模式…

实时定位与路径优化:跑腿App系统开发中的地理信息技术

本文将介绍如何使用地理信息技术实现实时定位和路径优化功能&#xff0c;以提高跑腿服务的效率。 实时定位 用户位置获取 # 示例&#xff1a;获取用户的实时位置 def get_user_location(user_id):# 使用GPS或网络定位技术获取用户的地理坐标# 返回经度和纬度信息return lon…

随笔记录-springboot_ConfigFileApplicationListener

SimpleApplicationEventMulticaster、 BootstrapApplicationListener、ConfigFileApplicationListener 加载流程 SpringApplication#run(java.lang.Class<?>[], java.lang.String[]) SpringApplication#run(java.lang.String…) SpringApplication#prepareEnvironment…

竞赛选题 深度学习火车票识别系统

文章目录 0 前言1 课题意义课题难点&#xff1a; 2 实现方法2.1 图像预处理2.2 字符分割2.3 字符识别部分实现代码 3 实现效果4 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 图像识别 火车票识别系统 该项目较为新颖&#xff0c;适…

Pod控制器详解

目录 一、Pod控制器及其功用 二、Deployment控制器 三、StatefulSet控制器 四、DaemonSet控制器 五、Job控制器 六、CronJob 控制器 一、Pod控制器及其功用 Pod控制器&#xff0c;又称之为工作负载&#xff08;workload&#xff09;&#xff0c;是用于实现管理pod的中间层…

DNS(Domain Name System) in detail

什么是 DNS&#xff1f; DNS&#xff08;域名系统&#xff09;为我们提供了一种与互联网上的设备进行通信的简单方法&#xff0c;而无需记住复数。就像每个房子都有一个唯一的地址来直接向它发送邮件一样&#xff0c;互联网上的每台计算机都有自己唯一的地址来与之通信&#xf…

Vue+OpenLayers 创建地图并显示鼠标所在经纬度

1、效果 2、创建地图 本文用的是高德地图 页面 <div class"map" id"map"></div><div id"mouse-position" class"position_coordinate"></div>初始化地图 var gaodeLayer new TileLayer({title: "高德地…

老李测评:网络电视盒子哪个好?双十一必看电视盒子推荐

大家好&#xff0c;我是测评人老李&#xff0c;双十一大促期间我们都在买买买&#xff0c;本期老李要分享的数码产品推荐是电视盒子&#xff0c;为了推荐更客观&#xff0c;老李购入了各平台热销的十几款电视盒子&#xff0c;通过两周的对比后&#xff0c;整理了这份电视盒子推…

Python中通过socketserver库创建服务端

socketserver库是Python的标准库&#xff0c;提供了套接字服务端的框架&#xff0c;通过该框架可以简化服务端的创建流程。 1 socketserver库的导入 通过如图1显示的代码导入socketserver库。 图1 导入socketserver库 2 通过socketserver库创建TCP服务端 通过socketserver库…

​轻量应用服务器是什么?和云服务器的区别有哪些

在当今快速发展的应用开发和网站建设领域&#xff0c;选择合适的服务器配置是一个相当重要的事。作为当前最优质的海外服务器服务商&#xff0c;现在也受到了越来越多用户的欢迎&#xff0c;而在近几年的服务器领域&#xff0c;轻量应用服务器是一个备受关注的服务器类型&#…

pg14-sql基础(二)-排序与条件

排序 SELECT employee_id, first_name, last_name, hire_date, salary FROM employees ORDER BY first_name; --按字母&#xff0c;默认升序 ORDER BY hire_date ASC; --升序 ORDER BY hire_date DESC; --降序SELECT employee_id, first_name, last_name, hire_date, salary F…

Redis系列-Redis数据类型【3】

目录 Redis系列-Redis数据类型【3】字符串类型&#xff08;String&#xff09;SDS (simple dynamic string) 哈希类型&#xff08;Hash&#xff09;列表类型&#xff08;List&#xff09;集合类型&#xff08;Set&#xff09;有序集合类型&#xff08;ZSet&#xff09;字符串类…

关于视频封装格式和视频编码格式的简介

文章目录 简介视频封装格式&#xff08;Video Container Format&#xff09;视频编码格式&#xff08;Video Compression Format&#xff09;两者关系总结webm 格式简介webm视频编码格式webm音频编码格式webm总结 简介 视频封装格式&#xff08;Video Container Format&#x…