直线上最多的点数【php版】

47 篇文章 1 订阅

在这里插入图片描述

思路:对于点A、B、C,如何确定三点共线呢?
首先线段AB、AC的斜率是相同的,为了更好地比较,求出AB的横纵坐标之差dx,dy后,将其按最大公约数化简,然后我们,记一个key为"dx : dy",将其保存在一个map中,对应的value为2(表示该直线上已经有AB两个点了);同样地,我们对AC进行如上处理,如果key相同,则说明ABC在同一条直线上(它们有相同起点A),我们再将value+1;
为了不重复计算,我们记同线的点的最大数目为max,
我们遍历points,取位置为i的点为起点,0 <= i < len - 1; 然后从 j = i+1开始遍历,j < len, 看有多少点在以i为起点的线上,并更新max的值。
这样每次外层遍历,能找到符合的点最大数目不超过 len - i ,所以当max >= len -i ,就可以不循环了;
另外,当max的值超过len的一半时,max的值就是我们要求的,也可以跳出循环;(这个画图就很好理解)

代码如下:

<?php
class Solution {

	/**
	 * @param Integer[][] $points
	 * @return Integer
	 */
	function maxPoints($points) {
		$len = count($points);
		if ($len < 2) {
			return $len;
		}
		$maxNum = 0;
		for($i=0; $i<$len-1; $i++) {
			if ($maxNum > intdiv($len, 2) || $maxNum >= $len - $i) {
				break;
			}
			// 用于记录每一趟,多少点在以i开头的线上
			$ansMp = [];
			for ($j=$i+1; $j<$len; $j++) {
				$dx = $points[$j][0] - $points[$i][0];
				$dy = $points[$j][1] - $points[$i][1];

				if ($dx == 0) {
					$dy = 1;
				} else if ($dy == 0) {
					$dx = 1;
				} else {
					// 保证 -2,1  与 2,-1的结果一致
					if ($dy < 0) {
						$dy = -$dy;
						$dx = -$dx;
					}
					$gcd = $this->gcd($dx, $dy);
					$dx = $dx / $gcd;
					$dy = $dy / $gcd;
				}
				$key = $dx . ':' . $dy;
				if (array_key_exists($key, $ansMp)) {
					++$ansMp[$key];
				} else {
					$ansMp[$key] = 2;
				}
			}
			foreach ($ansMp as $num) {
				$maxNum = max($maxNum, $num);
			}
		}
		return $maxNum;
	}

	function gcd($x, $y) {
		return $y ? $this->gcd($y, $x % $y) : $x;
	}
}

$s = new Solution();
var_dump($s->maxPoints([[0,0],[4,5],[7,8],[8,9],[5,6],[3,4],[1,1]]));

执行结果:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值