Leetcode149:直线上最多的点数

128 篇文章 1 订阅

给定一个二维平面,平面上有 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

解法1 查找表

第一次尝试时使用了double来存放斜率,但是在执行测试用例[ [0,0] , [94911151, 94911150] , [94911152, 94911151] ]时没有通过,原因是double的精度不够,所以换用了BigDecimal来存放斜率
在leetcode的ac列表发现了这样的沙雕解法:
在这里插入图片描述
这个人就是没考虑到精度的问题,直接把这个测试用例跳过了2333.
在看别人的解法时发现,其实可以不用除法来算两个点之间的斜率,而使用内外项之积来代表斜率,这样就不会出现精度的问题了.详解见解法2

	public int maxPoints(Point[] points) {

		int ret = 0;
		for (int i = 0; i < points.length; i++) {
			//map记录与i点连成的线斜率为key的点的个数
			Map<BigDecimal, Integer> map = new HashMap<>();
			for (int j = i + 1; j < points.length; j++) {
				//两点确定一条直线 ,确定两点后,斜率也随之确定了
				BigDecimal slope = getSlope(points[i], points[j]);
				map.put(slope, map.getOrDefault(slope, 0) + 1);
			}
			for (BigDecimal slope : map.keySet()) {
				if (slope!=null){
					ret = map.get(slope)+map.getOrDefault(null,0)>ret?map.get(slope)+map.getOrDefault(null,0):ret;
				}else {
					ret = map.get(slope)>ret?map.get(slope):ret;
				}
			}
		}
		return points.length > 0 ? ret + 1 : 0;
	}

	//得到两点连线的斜率
	private BigDecimal getSlope(Point p1, Point p2) {
		//两点为同一点的情况
		if (p1.x == p2.x && p1.y == p2.y) {
			return null;
		}
		//斜率不存在的情况
		if (p1.x == p2.x) {
			return BigDecimal.valueOf(Double.MAX_VALUE);
		}
		//斜率为0的情况
		if (p1.y == p2.y) {
			return BigDecimal.valueOf(0);
		}
		return BigDecimal.valueOf (p1.y - p2.y).divide(BigDecimal.valueOf(p1.x - p2.x),20,BigDecimal.ROUND_HALF_DOWN);

	}

	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[]) {
		List<Point> list = Arrays.asList(new Point(1, 0),new Point(1,1), new Point(0, 0));
		Point[] points = (Point[]) list.toArray();
		System.out.println(new Solution149().maxPoints(points));
	}

解法2 用乘积来保存斜率

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值