LeetCode(149):直线上最多的点数 Max Points on a Line + 浮点数比较(Java)

234 篇文章 1 订阅
177 篇文章 0 订阅

2019.4.9 #程序员笔试必备# LeetCode 从零单刷个人笔记整理(持续更新)
看着自己半年之前写的代码,还真是有点稚嫩呀。这是我刷的第一道Hard题。
这道题只需要把计算所有点两两的斜率,将斜率相同的点出现的次数进行记录,求出次数最多的斜率即可。需要注意的点是:
1.注意斜率为无穷大的点对。
2.用除法计算斜率无法通过大数用例(除后约为0),需要改用比例法代替。


传送门:直线上最多的点数

Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.

给定一个二维平面,平面上有 n 个点,求最多有多少个点在同一条直线上。

示例 1:
输入: [[1,1],[2,2],[3,3]]
输出: 3
解释:
^
|
|        o
|     o
|  o  
+------------->
0  1  2  3  4

示例 2:
输入: [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]]
输出: 4
解释:
^
|
|  o
|     o        o
|        o
|  o        o
+------------------->
0  1  2  3  4  5  6

/**
 * 
 * @author ChopinXBP Given n points on a 2D plane, find the maximum number of
 *         points that lie on the same straight line. 给定一个点集,判断最多有多少个点在一条直线上。
 *         注意点:1.double数据的比较,2.斜率法不适用于大数数据点
 *
 */

public class MaxPointsOnALine {

	public static class Point {
		int x;
		int y;
		Point() {
			x = 0;
			y = 0;
		}
		Point(int a, int b) {
			x = a;
			y = b;
		}
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		// Point[] points = {new Point(1,2), new Point(1,3), new Point(2,4), new
		// Point(3,6), new Point(2,6)};
		// Point[] points = {new Point(3,10), new Point(0,2), new Point(0,2), new
		// Point(3,10)};
		// 斜率法能够过牛客的测试点,但是却过不了以下LeetCode的测试点,可以考虑用比例法,用(y2-y0)*(x2-x1)==(y2-y1)*(x2-x0)
		Point[] points = { new Point(0, 0), new Point(94911151, 94911150), new Point(94911152, 94911151) };
		System.out.println(maxPoints(points)); // 斜率法
		System.out.println(maxPoints2(points)); // 比例法
	}

	// 斜率法
	public static int maxPoints(Point[] points) {
		// 排除不足3个点的情况
		if (points.length <= 2)
			return points.length;

		int max = 2;
		for (int i = 0; i < points.length - 1; i++) {
			for (int j = i + 1; j < points.length; j++) {
				int count = 2;
				// 斜率不为无穷
				if ((points[i].x != points[j].x)) {
					double k = (double) (points[i].y - points[j].y) / (points[i].x - points[j].x);
					double b = (double) points[i].y - points[i].x * k;
					int m = 0;
					while (m < points.length) {
						if (m != i && m != j && isEqual(points[m].y, k * points[m].x + b))
							count++;
						m++;
					}
					if (count > max)
						max = count;
				}
				// 斜率为无穷大
				else {
					int m = 0;
					while (m < points.length) {
						if (m != i && m != j && points[m].x == points[i].x)
							count++;
						m++;
					}
					if (count > max)
						max = count;
				}
			}
		}
		return max;
	}

	// 比例法
	public static int maxPoints2(Point[] points) {
		// 排除不足3个点的情况
		if (points.length <= 2)
			return points.length;

		int max = 2;
		for (int i = 0; i < points.length - 1; i++) {
			for (int j = i + 1; j < points.length; j++) {
				int count = 2;
				// 斜率不为无穷
				if ((points[i].x != points[j].x)) {
					int m = 0;
					double y = 10000.0 * (double) (points[i].y - points[j].y);
					double x = 10000.0 * (double) (points[i].x - points[j].x);
					while (m < points.length) {
						if (m != i && m != j) {
							double y2 = 10000.0 * (double) (points[i].y - points[m].y);
							double x2 = 10000.0 * (double) (points[i].x - points[m].x);
							if (isEqual(x2 * y, y2 * x))
								count++;
						}
						m++;
					}
					if (count > max)
						max = count;
				}
				// 斜率为无穷大
				else {
					int m = 0;
					while (m < points.length) {
						if (m != i && m != j && points[m].x == points[i].x)
							count++;
						m++;
					}
					if (count > max)
						max = count;
				}
			}
		}
		return max;
	}

	// 浮点数相等比较
	public static boolean isEqual(double x1, double x2) {
		// 比较方法1
		if ((x1 - x2 <= 0.0000001) && (x1 - x2 >= -0.0000001)) {
			return true;
		} else {
			return false;
		}

		// 比较方法2
		// if(Double.doubleToLongBits(x1) == Double.doubleToLongBits(x2)){
		// return true;
		// }else{
		// return false;
		// }

		// 比较方法3
		// if(Double.toString(x1).equals(Double.toString(x2))){
		// return true;
		// }else{
		// return false;
		// }
	}
}


#Coding一小时,Copying一秒钟。留个言点个赞呗,谢谢你#

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值