max points on a line

文章目录


题目内容

意思:在一个二维平面上有n个点,求出现在同一直线上的点(就是那n个点)的最大个数。

尝试一

结果:case通过率为7.69%

代码:

/**
 * Definition for a point.
 * class Point {
 *     int x;
 *     int y;
 *     Point() { x = 0; y = 0; }
 *     Point(int a, int b) { x = a; y = b; }
 * }
 */
public class Solution {
     /**
     * 思路:1.for循环求直线
     *      2.for循环判断点是否在该直线上
     * @param points 
     * @return
     */
    public int maxPoints(Point[] points) {
        /*特殊情况处理*/
        if(points==null ){
            return 0;
        }
        if(points.length==1){
            return 1;
        }

       
        boolean[] marks=new boolean[points.length];
        int max=0;
        for(int i=0;i<points.length;++i){
            for(int j=(i+1)%points.length;j!=i;++j){
                if(marks[j]==true){
                    continue;
                }
                /* 开始连线*/
                int count=0;
                if(points[i].x==points[j].x){/*特殊情况:斜率不存在*/
                    for(int z=0;z<points.length;++z){
                        if(points[z].x==points[i].x){
                            count++;
                        }
                    }
                    if(count>max){
                        max=count;
                    }
                }else{/*一般情况,斜率存在*/
                    //斜率应该用double来存
                    double k;
                    if(points[i].y-points[j].y==0){
                        k=0;
                    }else {
                        k=1.0*(points[i].y - points[j].y) / (points[i].x - points[j].x);
                    }

                    double b=points[i].y - (k*points[i].x);


                    /*for循环确定该线(斜率存在)上的点的个数*/
                    for(int z=0;z<points.length;++z){
                        if(k*points[z].x+b-points[z].y < 1e-12){
                            count++;
                        }
                    }
                    
                    if(count>max){
                        max=count;
                    }

                }
            }
            //当point[i]与其他点的所有联系情况都尝试过了,就表明这个点不可用了
            marks[i]=true;
        }

        return max;
    }
}

测试用例:

不通过
您的代码已保存
答案错误:您提交的程序没有通过所有的测试用例
case通过率为7.69%

用例:
[(0,0),(0,0)]

对应输出应该为:

2

你的输出为:

java.lang.ArrayIndexOutOfBoundsException: 2

分析:没想到竟然可以存在重复的点。

尝试2

结果:答案正确:恭喜!您提交的程序通过了所有的测试用例
代码:

import java.util.*;
/**
 * Definition for a point.
 * class Point {
 *     int x;
 *     int y;
 *     Point() { x = 0; y = 0; }
 *     Point(int a, int b) { x = a; y = b; }
 * }
 */
public class Solution {
      /**
     * 思路:1.for循环求直线
     *      2.for循环判断点是否在该直线上
     * @param points
     * @return
     */
    public int maxPoints(Point[] points) {
        /*特殊情况处理*/
        if(points==null || points.length==0 ){
            return 0;
        }
        /*todo 去重*/
        Arrays.sort(points, new Comparator<Point>() {
            @Override
            public int compare(Point o1, Point o2) {
                if(o1.x==o2.x && o1.y==o2.y){
                    return 0;
                }else if(o1.x*o1.x+o1.y*o1.y>o2.x*o2.x+o2.y*o2.y){
                    return 1;
                }else{
                    return  -1;
                }
            }
        });
        ArrayList<Point> pA=new ArrayList<>();
        pA.add(points[0]);
        for(int i=1;i<points.length;++i){
            if(points[i].x==points[i-1].x && points[i].y==points[i-1].y){
                continue;
            }
            pA.add(points[i]);
        }

        /*另一种特殊情况,全为重复点*/
        if(pA.size()==1){
            return points.length;
        }


        boolean[] marks=new boolean[pA.size()];
        int max=0;
        for(int i=0;i<pA.size();++i){
            for(int j=(i+1)%pA.size();j!=i;j=(++j)%pA.size()){
                if(marks[j]==true){
                    continue;
                }
                /* 开始连线*/
                int count=0;
                if(pA.get(i).x==pA.get(j).x){/*特殊情况:斜率不存在*/
                    for(int z=0;z<points.length;++z){
                        if(points[z].x==pA.get(i).x){
                            count++;
                        }
                    }
                    if(count>max){
                        max=count;
                    }
                }else{/*一般情况,斜率存在*/
                    //斜率应该用double来存
                    double k;
                    if(pA.get(i).y-pA.get(j).y==0){
                        k=0;
                    }else {
                        k=1.0*(pA.get(i).y - pA.get(j).y) / (pA.get(i).x - pA.get(j).x);
                    }

                    double b=pA.get(i).y - (k*pA.get(i).x);


                    /*for循环确定该线(斜率存在)上的点的个数*/
                    for(int z=0;z<points.length;++z){
                        if(Math.abs( k*points[z].x+b-points[z].y) < 1e-12){
                            count++;
                        }
                    }

                    if(count>max){
                        max=count;
                    }

                }
            }
            //当point[i]与其他点的所有联系情况都尝试过了,就表明这个点不可用了
            marks[i]=true;
        }

        return max;
    }
}

结论

  1. 一个数组,从第i位开始遍历(但不报第i位)。初识循环变量时与循环变量增加时分别取余:
 int p[]={1,2,3,5};
 int i=2;
 for(int j=(i+1)%p.length;j!=i;j=(++j)%p.length){
 }
  1. double比较大小是不能用a==b,而是a-b<1e-12。
  2. double判断是否为0,要Math.abs( k*points[z].x+b-points[z].y) < 1e-12。要取绝对值
  3. double能够精确到15位。参考 Java中float/double取值范围与精度
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值