【LeetCode】直线上最多的点数 [H](几何)

news2024/11/25 12:52:53

149. 直线上最多的点数 - 力扣(LeetCode)

一、题目

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

示例 1:

输入:points = [[1,1],[2,2],[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 <= 104
  • points 中的所有点 互不相同

二、代码

class Solution {
    public static int maxPoints(int[][] points) {
        int n = points.length;
        int max = 1;
        // 斜率表,单独记录分子和分母
        // key = 3  表示斜率的分子
		// value = {7 , 10}  -> 斜率为3/7的点 有10个
		//         {5,  15}  -> 斜率为3/5的点 有15个
        HashMap<Integer, HashMap<Integer, Integer>> fractionMap = new HashMap<>();
        // 开始从左往右去以(points[i][0], points[i][1])为基础,然后i后面的所有的点与(points[i][0], points[i][1])进行连线,看最多有多少个共线的点
        // 不用判断i之前的位置,因为i之前的位置一定是都判断过了。这里每一轮其他的点都要去连(points[i][0], points[i][1]),因为只有斜率相等且过同一个点才算是共线
        for (int i = 0; i < n - 1; i++) {
            // 记录本轮查询共线的四种情况分别的节点个数
            // 与(points[i][0], points[i][1])在同一个位置的(points[j][0], points[j][1])节点个数
            int cnt1 = 1;
            // 与(points[i][0], points[i][1])的连线在同一竖线的(points[j][0], points[j][1])节点个数
            int cnt2 = 1;
            // 与(points[i][0], points[i][1])的连线在同一横线的(points[j][0], points[j][1])节点个数
            int cnt3 = 1;
            // 与(points[i][0], points[i][1])的连线斜率相等的(points[j][0], points[j][1])节点个数
            int cnt4 = 1;
            // 本轮查询最大的与(points[i][0], points[i][1])共线的节点个数
            int cnt = 0;
            // 斜率分子
            int molecule;
            // 斜率分母
            int denominator;
            // 斜率分子和分母的最小公约数,用于化简斜率分数
            int gcd;
            // 每一轮要清空map,因为斜率相同并不意味着在同一条直线,只有斜率相同,并且过同一个点的两条线才是在同一条直线上。所以到了下一轮之后,所有点共同连线的点就变了,以前的map就都要清空了,因为两轮即使计算出了相同的斜率,因为并不过同一个点,也不是共线的。
            fractionMap.clear();

            // 他俩不用去做化简,在后面与其他点计算得到斜率分数的时候,再去做分数化简即可。
            int x = points[i][0];
            int y = points[i][1];
           
            // 开始将i右边的所有点和(points[i][0], points[i][1])进行连线,判断有多少个是相同点、共横线、共竖线、共斜率的。
            for (int j = i + 1; j < n; j++) {
                // 共点
                if (x == points[j][0] && y == points[j][1]) {
                    cnt1++;
                    // 看共点的数量是否能够超过cnt
                    cnt = Math.max(cnt, cnt1);
                // 共竖线
                } else if (x == points[j][0]) {
                    cnt2++;
                    cnt = Math.max(cnt, cnt2);
                // 共横线
                } else if (y == points[j][1]) {
                    cnt3++;
                    cnt = Math.max(cnt, cnt3);
                // 判断是否是共斜率
                } else {
                    // 计算(points[i][0], points[i][1])和(points[j][0], points[j][1])连线的斜率的分子和分母
                    molecule = x - points[j][0];
                    denominator = y - points[j][1];
                    // 计算分子和分母的最大公约数,将分数进行化简
                    gcd = gcd(molecule, denominator);
                    // 分数化简
                    molecule = molecule / gcd;
                    denominator = denominator / gcd;
                    // 用已经化到最简的斜率分数加入到斜率表fractionMap中,并且得到当前此斜率涉及到的节点个数
                    cnt4 = add(molecule, denominator, fractionMap);
                    // 相同斜率的节点数量是否能够超过cnt
                    cnt = Math.max(cnt, cnt4);

                }
            }
            // 本轮统计完毕,看本轮的个数是否能推高最大值max
            max = Math.max(max, cnt);
        }

        return max;
    }

    // 求a和b的最大公约数:辗转相除法
    public static int gcd(int a, int b) {
        int c = a % b;
        if (c == 0) {
            return b;
        } else {
            return gcd(b, c);
        }
    }

    // 将一个新的斜率x/y加入到斜率表fractionMap中,同时更新这个斜率的直线涉及到的节点数。并且返回这个斜率已有的设计节点的个数
    public static int add(int x, int y, HashMap<Integer, HashMap<Integer, Integer>> fractionMap) {
        // 一定要先判断此时斜率表有没有斜率分子为x的键值对,如果没有,需要先创建一个斜率为x的键值对
        if (!fractionMap.containsKey(x)) {
            HashMap<Integer, Integer> map = new HashMap<>();
            fractionMap.put(x, map);
        }

        // 判断此时有没有分子为x,分母为y的value。注意这里保证一定是有分子为x的value的,因为即使没有上面的操作也已经创建好了
        // 因为可能有很多斜率虽然不同,但是分子是相同的,所以即使不存在x/y的斜率,但是分子为x的可能还会有其他的斜率,所以这里并不能直接创建一个新的HashMap<Integer, Integer>作为x的value,否则会将其他斜率的有效数据给抹掉。
        if (!fractionMap.get(x).containsKey(y)) {
            // 如果此时没有x/y的斜率,就创建一个HashMap<Integer, Integer>,将y加入,并且初始化节点个数为2
            HashMap<Integer, Integer> map = fractionMap.get(x);
            map.put(y, 2);
            fractionMap.put(x, map);
            // 返回x/y这个斜率涉及到的节点个数
            return 2;
        } else {
            // 如果已经有x/y的斜率了,则将这个斜率的节点个数加1
            HashMap<Integer, Integer> map = fractionMap.get(x);
            int cnt = map.get(y);
            map.put(y, cnt + 1);
            fractionMap.put(x, map);
            return cnt + 1;
        }
    }
}

三、解题思路 

大流程,来到一个点时候没有必要看前面的,就来到一个点就和它后面的点计算判断,没有必要看前面的,因为在之前前面的点一定已经和自己计算过了,所以如果后面又看一遍就算重了。

所以我们流程就变成了来到a的时候后面的节点搞一下,看看后面的点有多少个和a的连线是同一条直线;来到b的时候后面的节点搞一下,看看后面的点有多少个和a的连线是同一条直线;到c的时候后面的节点搞一下,看看后面的点有多少个和a的连线是同一条直线;不用往前重复求了,就是我们的大流程。

怎么表示斜率,两个点(X1,Y1)和(X2,Y2),斜率就是(X1 - X2)/ (Y1 - Y2)。

我们每一轮判断,肯定是要固定一个点,让其他所有的的点都和这个点做连线,然后通过下面的四种情况判断是不是共线。

那么判断多个点共线(每一轮判断一定是保证所有的点都会和同一个点做连线看他们斜率是否相等,这种情况下只要是斜率相等,那么这几个点一定就是共线的),一共有如下四个情况:

  1. 正常的斜率,几个点连线的斜率都是相同的。
  2. 共点,如果两个点是在同样一个位置,也是算共线的。
  3. 在同一个水平线上,也就是Y坐标相等,即斜率都是0。
  4. 在同一条竖线上,也就是X坐标相等。

最终答案每一轮共横线的、共竖线的、共点的、以及在同一个斜率上的所有点的个数,你给我求个max。这个max就是本轮共线的点的最多个数。然后后面将所有都统计一边,每一轮的max再求一个最大值,这个最大值就是最终的答案。

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

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

相关文章

【数据结构与算法分析】0基础带你学数据结构与算法分析11--AVL树

目录 二分查找 AVL 树 AVL 的平衡因子 AVL 的插入操作 单旋转 双旋转 对 AVL 树插入的总结 AVL 的移除操作 如果给定一个序列&#xff0c;你将如何在这个序列中查找一个给定元素 target&#xff0c;当找到时返回该元素的迭代器&#xff0c;否则返回末尾迭代器。首先排除…

python基于flask搭建http服务(二)—— 实现Excel上传、数据清洗、入库

一、技术点 利用flask 搭建简易的http服务,实现服务端文件上传;利用Blueprint将不同业务拆分至不同文件;利用bootstrap-fileinput组件构建页面;利用flask_cors配置允许跨域请求;利用sqlalchemy实现数据库连接;利用pandas实现Excel读取、清洗、入库;二、具体实现 2.1 目…

基于intel i3/i5/i7 视觉控制器 4个POE GigE

XM-5143 是针对机器视觉行业GigE相机应用场景的一款高性能工业计算机&#xff0c;可使用Intel 6/7代 65W 高性能CPU应对快速检测。4路独立Intel网络芯片&#xff0c;并支持POE供电&#xff0c;可减少布线。并配有快速隔离可编程DI/O芯片. XM-5143的规格产品类型机器视觉控制器防…

分布式事务都有哪些,到底有什么用,在项目当中该用哪个?

分布式的CAP理论应该是人尽皆知了&#xff0c;它描述了一致性&#xff08;C&#xff09;、可用性&#xff08;A&#xff09;、分区容错性&#xff08;P&#xff09;的一系列权衡。很多时候&#xff0c;我们要在一致性和可用性之间权衡&#xff0c;而分布式事务&#xff0c;就是…

20.EC实战 笔记本电脑的休眠唤醒是如何实现的

文章目录 1. EC什么时候(收到什么命令)之后来执行S0-->S3下电时序?2. S3(休眠)状态应该保留哪些电源?3. 控制笔记本进入休眠状态的三种方式总结:前言: 最近很多朋友在咨询休眠唤醒的问题,在笔记本中,休眠唤醒是一个基本功能,如果连休眠唤醒都没有,就失去了笔记本…

Volatile内存语义以及如何正确使用

目录 语义描述 重排序规则 JMM如何实现volatile语义 如何正确使用volatile变量 语义描述 写语义&#xff1a;当写一个volatile变量时候&#xff0c;JMM会把该线程对应的本地内存的共享变量直接刷新到主内存中。 读语义&#xff1a;当读一个volatile变量的时候。JMM会把该线…

分布式锁主动续期的入门级实现-自省 | 简约而不简单

一、背景 如果某个客户端获得锁之后处理时间超过最大约定时间&#xff0c;或者持锁期间内发生了故障导致无法主动释放锁&#xff0c;其持有的锁也能够被其他机制正确释放&#xff0c;并保证后续其它客户端也能加锁&#xff0c;整个处理流程继续正常执行。 简单解释一下&#xf…

LLeetCode题目笔记——6258. 数组中最长的方波

文章目录题目描述题目难度——中等方法一&#xff1a;一次遍历哈希代码Python暴力代码Python一次遍历总结题目描述 这是这周周赛的第二题&#xff0c;本来想是不是双指针的解法&#xff0c;但想半天没想出来咋用双指针&#xff0c;就想到了哈希。 给你一个整数数组 nums 。如果…

PostgreSQL数据库TPCC测试,Banchmarksql 5.0部署详解

1 BenchmarkSQL安装部署 1.1 部署Java环境 首先使用java - version查看是否已有 Java环境&#xff08;下图是有的情况&#xff09; 需要注意的是&#xff0c;虚拟机中默认的JDK貌似是不行的哦&#xff0c;请参考下面链接中的博文&#xff0c;教你怎么卸载重装 1.1.1 若没有J…

Python学习基础笔记四十四——模块1

1、看一个例子&#xff1a; 创建一个demo.py文件&#xff1a; print(in demo.py)def hello():print(in hello function) 然后我们在另外一个文件中import这个demo文件&#xff1a; import demo# 调用demo.py文件中的hello()函数 demo.hello() 注意&#xff0c;demo后面没有…

软件安全测试-BurpSuite使用详解

1.BurpSuite简介 Burp Suite 是用于攻击web 应用程序的集成平台&#xff0c;它包含了许多Burp工具&#xff0c;这些不同的burp工具通过协同工作&#xff0c;有效的分享信息&#xff0c;支持以某种工具中的信息为基础供另一种工具使用的方式发起攻击。 它主要用来做安全性渗透测…

我将 9 个 ChatGPT 账号接入微信,我现在整个人都麻了...

大家好&#xff0c;我是米开朗基杨。最近大家都被 ChatGPT 刷屏了&#xff0c;这家伙真是上天入地无所不能&#xff0c;不管什么问题都能解答&#xff0c;而且答案的质量非常高&#xff0c;完全不像机器人。于是乎我冒出个想法&#xff1a;如果把 ChatGPT 接入微信是什么感觉&a…

二维码介绍

二维码介绍 二维码&#xff08;2-dimensional bar code、二维条码&#xff09;是用某种特定的几何图形按一定规律在平面&#xff08;二维方向上&#xff09;分布的、黑白相间的、记录数据符号信息的图形&#xff1b;在代码编制上巧妙地利用构成计算机内部逻辑基础的“0”、“1…

repo的安装和使用

前言 Android 采用 Gerrit 提供代码评审服务&#xff0c;并且开发了一个客户端工具 repo&#xff0c;实现多仓库管理。Git 的开发者对服务端的 Git 源码做了扩展&#xff0c;使得基于 Git&#xff08;cgit&#xff09;的代码平台可以很容易引入新的集中式工作流。同样 git-rep…

概率统计·参数估计【矩估计、极大似然估计、无偏性、有效性、相合性】

点估计 设总体的分布函数形式已知&#xff0c;但它的一个或多个参数为未知&#xff0c;借助于总体的一个样本来估计总体未知参数的值的问题称为点估计问题 矩估计 这个还是看例子会比较好理解一些 例 先μ1E(x)&#xff0c;μ2E(x2)有几个未知参数就列几次方的期望&#xff…

CSS -- 01. CSS基础

文章目录CSS基础1 CSS简介1.1 HTML的局限性1.2 CSS介绍1.3 CSS语法规范1.4 CSS代码风格2 CSS基础选择器2.1 选择器的分类2.2 标签选择器2.3 **类选择器**2.4 id选择器2.5 通配符选择器2.6 基础选择器总结3 CSS字体属性3.1 字体系列3.2 字体大小3.3 字体粗细3.4 文字样式3.5 字体…

[附源码]JAVA毕业设计医药垃圾分类管理系统(系统+LW)

[附源码]JAVA毕业设计医药垃圾分类管理系统&#xff08;系统LW&#xff09; 项目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目…

Day827.安全性、活跃性以及性能问题 -Java 并发编程实战

安全性、活跃性以及性能问题 Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于安全性、活跃性以及性能问题的内容。 并发编程中需要注意的问题有很多&#xff0c;主要有三个方面&#xff0c;分别是&#xff1a; 安全性问题活跃性问题性能问题 一、安全性问题 相信一…

论文讲解p2p4

本人水平有限,很多地方可能有说错或者理解错的地方请指出,谢谢谅解 一.原始电路图 1.简介:本电路是从1977年一篇电荷重新分配的理念进化而来,论文如下: All-MOS charge redistribution analog-to-digital conversion techniques. --JAMES L. McCREARY 2.因为从一开始充电过…

Java使用H2数据库全方式汇总

H2是轻量级数据库&#xff0c; 可以不需要安装就可以运行&#xff0c;对于快速学习和演示比较适用。关于H2的基本内容可以参考&#xff1a; H2 数据库简介 。 本篇快速介绍H2数据库在各种类型的Java应用中的使用&#xff0c; 包括&#xff1a; Java 项目Java Web 项目Spring B…