这道题的题意是给出一定数量的点,在同一条线上的点的最大个数
思路是,遍历每一个点,算出这个点与其他点的斜率,如果斜率相同,则说明这些点在同一条直线上
需要注意的是,存在重复的点和与x轴垂直的点,需要单独考虑
在牛客网上通过的代码(leetcode网上没有通过)
import java.util.HashMap;
public class max_points_on_a_line {
public int maxPoints(Point[] points) {
if(points.length < 2){
return points.length;
}
int result = 0;
for (int i = 0; i < points.length; i++){
Point a = points[i];
int max = 0;
int duplicate = 0;
int vertical = 0;
HashMap<Double, Integer> map = new HashMap<>();
for (int j = 0; j < points.length; j++){
if (j == i) continue;
Point b = points[j];
if (a.x == b.x){
if (a.y == b.y){
duplicate++;
}else {
vertical++;
}
}else {
double k = (double)(a.y - b.y)/(a.x - b.x);
if (map.get(k) == null){
map.put(k, 1);
}else {
map.put(k, map.get(k) + 1);
}
}
}
max = vertical;
for (double k : map.keySet()){
max = Math.max(max, map.get(k));
}
result = Math.max(result, max + duplicate);
}
return result;
}
}
然而以上代码在牛客网通过了,但是在leetcode上跑的时候没有通过,为啥呢?
因为leetcode上给出了一个测试用例,(0,0),(123456789,123456788),(123456787,123456788),对于这个例子来说,由于以上代码中存储的是double值,精度受限,所以以上代码算出来的这三个点是在同一条直线上的。然而,改进后的算法是将斜率k改为String,斜率具体用 分子/分母 的形式表示,其中分子和分母已进行约分,若果斜率为负值还需要添加 - 号。
leetcode上通过的代码为
/**
* Definition for a point.
* class Point {
* int x;
* int y;
* Point() { x = 0; y = 0; }
* Point(int a, int b) { x = a; y = b; }
* }
*/
class Solution {
public int maxPoints(Point[] points) {
if(points.length < 2){
return points.length;
}
int result = 0;
for (int i = 0; i < points.length; i++){
Point a = points[i];
int max = 0;
int duplicate = 1;
int vertical = 0;
HashMap<String, Integer> map = new HashMap<>();
for (int j = 0; j < points.length; j++){
if (j == i) continue;
Point b = points[j];
if (a.x == b.x){
if (a.y == b.y){
duplicate++;
}else {
vertical++;
}
}else {
String k = null;
if ( a.y == b.y){
k = "0";
}else {
int dy = a.y - b.y;
int dx = a.x - b.x;
int common = getCommon(Math.abs(dy), Math.abs(dx));
String prefix = "";
if (dy * dx < 0){
prefix = "-";
}
k = prefix + (Math.abs(dy)/common) + "/" + (Math.abs(dx)/common);
}
if (map.get(k) == null){
map.put(k, 1);
}else {
map.put(k, map.get(k) + 1);
}
}
}
max = vertical;
for (String k : map.keySet()){
max = Math.max(max, map.get(k));
}
result = Math.max(result, max + duplicate);
}
return result;
}
private int getCommon(int a, int b) {
int r;
if ( a < b){
int temp = a;
a = b;
b = temp;
}
while (b != 0){
r = a % b;
a = b;
b = r;
}
return a;
}
}