求经过两点的直线的表达式(Leetcode.149)
在刷Leetcode的时候,第149题需要求经过两点的直线的表达式,所以总结一下如何用代码求出经过两点的直线的表达式
注:只考虑 x, y 为整数的情况,且不考虑计算中整型溢出的情况
求直线表达式需要解决的问题
1.求坐标系中经过两点的直线的表达式
表达式的形式为:y = a * x + b
根据两个点的坐标得到方程式:
①. y1 = a * x1 + b
②. y2 = a * x2 + b
得出 a 和 b 的表达式为(x1 - x2 不为 0 的情况下):
a = (y1 - y2)/(x1 - x2)
b = (x1 * y2 - x2 * y1)/(x1 - x2)
2.分数化简为真分数
由于 a, b 都可能为无限小数,且计算机存储浮点数存在精度问题,需要将 a, b 都用分数表示
若 a, b 不是真分数,那么同一条直线可能会有多条表达式,所以需要将 a, b 都化简为真分数
分数化简为真分数方法是:分子分母同时除以分子分母的最大公约数
3.求最大公约数
使用辗转相除法
求表达式相关代码
public class Util {private static final String ZERO = "0";/*** 求坐标系中经过两点的直线的表达式* <p>* 表达式的形式为:y = a * x + b* <p>* 根据两个点的坐标得到方程式:* ①. y1 = a * x1 + b* ②. y2 = a * x2 + b* <p>* 得出 a 和 b 的表达式为(x1 - x2 不为 0 的情况下):* a = (y1 - y2)/(x1 - x2)* b = (x1 * y2 - x2 * y1)/(x1 - x2)** @param point1 第一个点的坐标* @param point2 第二个点的坐标* @return 经过point1和point2的直线的表达式*/public static String getExpression(int[] point1, int[] point2) {if (point1.length != 2 || point2.length != 2) {throw new IllegalArgumentException("无效的点坐标");}if (point1[0] == point2[0] && point1[1] == point2[1]) {throw new IllegalArgumentException("两个点的坐标不能相同");}int x1 = point1[0];int y1 = point1[1];int x2 = point2[0];int y2 = point2[1];// 如果x1 == x2,无法套用公式,直接返回int denominator = x1 - x2;if (denominator == 0) {return "x = " + x1;}int numerator = y1 - y2;String a = fractionSimplification(denominator, numerator);numerator = x1 * y2 - x2 * y1;String b = fractionSimplification(denominator, numerator);String expression;if (ZERO.equals(a)) {expression = "y = " + b;} else if (ZERO.equals(b)) {expression = "y = " + a + " * x";} else {expression = "y = " + a + " * x + " + b;}return expression;}/*** 分数化简为真分数** @param denominator 分母* @param numerator 分子* @return 真分数 分子/分母*/public static String fractionSimplification(int denominator, int numerator) {if (denominator == 0) {throw new IllegalArgumentException("分母不能为0");}if (numerator == 0) {return ZERO;}String simpleFraction = new String();if (numerator % denominator == 0 && numerator / denominator != 0) {// 如果 分子/分母 为整数,相除的结果即为化简结果simpleFraction += numerator / denominator;} else {// 分数化简就是分母分子同时除以它们的最大公约数int gcd = gcd(denominator, numerator);simpleFraction = (numerator / gcd) + "/" + (denominator / gcd);}return simpleFraction;}/*** 求最小公倍数** @param a 第一个数* @param b 第二个数* @return 最小公倍数*/public static int gcd(int a, int b) {return b == 0 ? a : gcd(b, a % b);}public static void main(String[] args) {int[] a = {1, 1};int[] b = {1, 2};int[] c = {3, 2};int[] d = {1, 2};int[] e = {0, 0};int[] f = {1, 3};int[] g = {0, 1};int[] h = {1, 3};int[] i = {2, 4};int[] j = {5, 2};System.out.println(getExpression(a, b));System.out.println(getExpression(c, d));System.out.println(getExpression(e, f));System.out.println(getExpression(g, h));System.out.println(getExpression(i, j));}
}
解题
题目描述:
给你一个数组
points
,其中points[i] = [xi, yi]
表示 X-Y 平面上的一个点。求最多有多少个点在同一条直线上。
思路:
1.求出每两个点之间的直线表达式
2.统计每个表达式出现的次数,次数最多的表达式即为点最多的直线
3.根据表达式出现的次数求出点的个数:
n个点两两组合方式有 count = C(n, 2) = n!/(2! * (n-2)!) = (n² - n)/2 种 所以直线表达式的出现次数count与点的个数n之间的关系为: count = (n² - n)/2 解方程: Δ = √(b² - 4ac) = √(1/4 + 2 * count) n = 1/2 ± √(1/4 + 2 * count) ∵ count为非负整数 ∴ min(Δ) = 1/2 ∵ n > 0 ∴ n = 1/2 + √(1/4 + 2 * count)
代码:
import java.util.HashMap;
import java.util.Map;class Solution {private static final String ZERO = "0";/*** 求坐标系中经过两点的直线的表达式* <p>* 表达式的形式为:y = a * x + b* <p>* 根据两个点的坐标得到方程式:* ①. y1 = a * x1 + b* ②. y2 = a * x2 + b* <p>* 得出 a 和 b 的表达式为(x1 - x2 不为 0 的情况下):* a = (y1 - y2)/(x1 - x2)* b = (x1 * y2 - x2 * y1)/(x1 - x2)** @param point1 第一个点的坐标* @param point2 第二个点的坐标* @return 经过point1和point2的直线的表达式*/public static String getExpression(int[] point1, int[] point2) {if (point1.length != 2 || point2.length != 2) {throw new IllegalArgumentException("无效的点坐标");}if (point1[0] == point2[0] && point1[1] == point2[1]) {throw new IllegalArgumentException("两个点的坐标不能相同");}int x1 = point1[0];int y1 = point1[1];int x2 = point2[0];int y2 = point2[1];// 如果x1 == x2,无法套用公式,直接返回int denominator = x1 - x2;if (denominator == 0) {return "x = " + x1;}int numerator = y1 - y2;String a = fractionSimplification(denominator, numerator);numerator = x1 * y2 - x2 * y1;String b = fractionSimplification(denominator, numerator);String expression;if (ZERO.equals(a)) {expression = "y = " + b;} else if (ZERO.equals(b)) {expression = "y = " + a + " * x";} else {expression = "y = " + a + " * x + " + b;}return expression;}/*** 分数化简为真分数** @param denominator 分母* @param numerator 分子* @return 真分数 分子/分母*/public static String fractionSimplification(int denominator, int numerator) {if (denominator == 0) {throw new IllegalArgumentException("分母不能为0");}if (numerator == 0) {return ZERO;}String simpleFraction = new String();if (numerator % denominator == 0 && numerator / denominator != 0) {// 如果 分子/分母 为整数,相除的结果即为化简结果simpleFraction += numerator / denominator;} else {// 分数化简就是分母分子同时除以它们的最大公约数int gcd = gcd(denominator, numerator);simpleFraction = (numerator / gcd) + "/" + (denominator / gcd);}return simpleFraction;}/*** 求最小公倍数** @param a 第一个数* @param b 第二个数* @return 最小公倍数*/public static int gcd(int a, int b) {return b == 0 ? a : gcd(b, a % b);}public static int maxPoints(int[][] points) {// 先获取每个点与其它任一点构成的直线表达式,并统计每个表达式的数量Map<String, Integer> expressionCountMap = new HashMap<>();for (int firstIndex = 0; firstIndex < points.length - 1; firstIndex++) {for (int secondIndex = firstIndex + 1; secondIndex < points.length; secondIndex++) {String expression = getExpression(points[firstIndex], points[secondIndex]);Integer count = expressionCountMap.get(expression);if (count == null) {expressionCountMap.put(expression, 1);} else {expressionCountMap.put(expression, count + 1);}}}// 出现次数最多的表达式即为点最多的直线的表达式int maxCount = 0;for (Map.Entry<String, Integer> entry : expressionCountMap.entrySet()) {if (entry.getValue() > maxCount) {maxCount = entry.getValue();}}// n个点两两组合方式有 C(n, 2) = n!/(2! * (n-2)!) = (n² - n)/2 种// 所以我们点最多的直线表达式的出现次数count与点的个数n之间的关系为: count = (n² - n)/2// 解方程:// Δ = √(b² - 4ac) = √(1/4 + 2 * count)// n = 1/2 ± √(1/4 + 2 * count)// ∵ count为非负整数// ∴ min(Δ) = 1/2// ∵ n > 0// ∴ n = 1/2 + √(1/4 + 2 * count)return (int) (0.5 + Math.sqrt((0.25 + 2 * maxCount)));}
}
求经过两点的直线的表达式(Leetcode.149)相关推荐
- [计算几何]知两点坐标求过两点的直线解析式
我们设已知点为 A ( X 1 , Y 1 ) A(X_1,Y_1) A(X1,Y1), B ( X 2 , Y 2 ) B(X_2,Y_2) B(X2,Y2) 它们的 X X X坐标差为 X ...
- python 求平面两点距离_Python求平面内点到直线距离的实现
近期遇到个问题,需要计算平面内点到直线的距离,发现数学知识都还给老师了,度娘后找到计算方法,特此记录. 点到直线的计算公式: 通过公式推导,得到信息: A:直线斜率 B:固定值-1 C:直线截距b 转 ...
- matlab已知三点求夹角,已知3点如何求其中两点对第3点的夹角
公告: 为响应国家净网行动,部分内容已经删除,感谢读者理解. 话题:已知3点如何求其中两点对第3点的夹角? 问题详情:有3个问题:1)已知3点如何求其中两点对第3点的夹角?2)如何回答:1)已知3点求 ...
- 求圆心到点的直线与圆的相交点
求圆心到点的直线与圆的相交点 点B为圆上一动点,已知圆心O(x2,y2), 圆外点A(x1,y1),圆半径r值,求B(x,y)坐标. 由图可知,产生下面两个公式. m/n = y1-y2/x1-x2 ...
- p点到(a,b)点两所在直线的垂点坐标及p点是否在(a,b)两点所在直线上
/// <summary> /// p点到(a,b)点两所在直线的垂点坐标 /// </summary> /// <pa ...
- AOJ GRL_1_C: All Pairs Shortest Path (Floyd-Warshall算法求任意两点间的最短路径)(Bellman-Ford算法判断负圈)
题目链接:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_1_C All Pairs Shortest Path Input ...
- C#求空间两点之间的距离
问题 求空间两点之间的距离 算法思想 d=sqrt(pow(x₁−x₂)+pow(y₁−y₂)+pow(z₁−z₂))d=sqrt(pow(x₁-x₂)+pow(y₁-y₂)+pow(z₁-z₂)) ...
- 使用Floyd-Warshall算法求出两点之间的最短路径
求出下面任意两个点之间的最短路径: 如何才能求出两点之间的最短路径呢?大家都知道学几何的时候,有一条定理就是:两点之间线段最短.但是在实际情况中,我往往两点之间没有之间的通路而是一些曲折的线路. 上面 ...
- Dijkstra最短路由算法,求任意两点之间的最短距离【Java】
一.问题 求下图中节点0到节点5之间的最短距离 二.方法 Dijkstra最短路由算法.本文不再赘述,直接上代码,如果不懂,可以参考 文章 三.代码 public class MyDijkstra { ...
最新文章
- CVPR2020 | 通过可微的代理投票损失进行6DoF对象位姿估计
- JAVA入门到精通-第71讲-学生管理系统3-增删改查
- 成功解决AttributeError: module ‘seaborn‘ has no attribute ‘lvplot‘
- spring cloud feign 加载流程
- 让思考成为一种习惯:一位软件工程专业学生的大学生涯规划
- java5年转c语言,时隔5年,C语言再次领先Java,荣登编程语言排行榜第一!
- SpringBoot笔记(二)
- 使用HTML5实现刮刮卡效果
- 前端学习(2009)vue之电商管理系统电商系统之渲染商品属性的结构
- ucc编译器(语法解析)
- 软件工程师如何应对面试的可怕“反乌托邦世界”?
- 2021牛客暑期多校训练营5,签到题BDHJK
- 【美团外卖】美食知识图谱的迭代及应用
- linux 内存坏了,Linux的缓存内存 Cache Memory详解
- android+显示ui布局,[Android ]UI布局 (线性布局+相对布局)
- 十大免费java开源商城系统
- [线性代数]向量2-范数三角不等式证明
- 【总结】1361- package.json 与 package-lock.json 的关系
- 清华大学鲍橒计算机1999,鲍橒从“最强大脑”到“盲棋第一人”
- C语言手机通讯录系统
热门文章
- 设置echarts雷达图label标签出现的位置聚拢或发散
- (74)Verilog实现CRC【MIPI】
- 安东尼罗宾--激发你的无限潜能[连载]--1 2章
- 给新手学习MySQL的建议
- OpenGL: 基础篇
- python所用到的英语单词_用python从字符串中提取英语单词
- 2016网络大事记 mark
- 笔记本电脑打开后不显示桌面_70后、80后、90后、00后……不一样的夏天打开方式,满满回忆!| 特别关注...
- matlab ob,Matlab 飞机航向INS仿真
- ai人工智能相关职业_2020年及以后的5个人工智能最佳职业