穷举法:max-points-on-a-line

Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.
析:此处的在一条直线上也包含斜的直线,因此分为水平竖直线、斜线两种情况。
如果是水平竖直线,直接以横坐标或纵坐标为参考作统计即可;
如果是斜线,得先把斜线定义成Line类,包含k b两个值,
之后分别统计每条斜线上的点的个数。
斜线那个方法的复杂度为o(n*n),因为创建斜线时需要双层循环。
自定义的类加上equals和hashCode方法

import java.util.*;

public class Main {
    public static void main(String[] args){
        Scanner sc= new Scanner(System.in);
        Main main = new Main();
        Point[] points =new Point[4];
        points[0]= new Point(3,10);
        points[1]= new Point(0,2);
        points[2]= new Point(0,2);
        points[3]= new Point(3,10);
        System.out.println(main.maxPoints(points));

    }

    public int maxPoints(Point[] points) {
        if(points==null || points.length==0)
            return 0;
        if(points.length==1)
            return 1;
        return Math.max(maxPoints1(points),maxPoints2(points));
    }
    // 考虑在水平线或竖直线
    public int maxPoints1(Point[] points) {
        // map为 <x或y的值,出现点的次数>
        Map<Integer,Integer> mapx = new HashMap<>();
        Map<Integer,Integer> mapy = new HashMap<>();
        for(Point p:points){
            if(!mapx.containsKey(p.x))
                mapx.put(p.x,1);
            else
                mapx.put(p.x, mapx.get(p.x)+1);

            if(!mapy.containsKey(p.y))
                mapy.put(p.y,1);
            else
                mapy.put(p.y, mapy.get(p.y)+1);
        }
        int max=0;
        for(Integer t:mapx.keySet()){
            max = max>mapx.get(t)?max:mapx.get(t);
        }
        for(Integer t:mapy.keySet()){
            max = max>mapy.get(t)?max:mapy.get(t);
        }

        return max;
    }

    // 考虑斜线
    public int maxPoints2(Point[] points) {
        Set<Line> lineSet = new HashSet<>();
        // <直线,直线上点的个数>
        Map<Line,Integer> map = new HashMap<>();
        for(int i=0;i<points.length;i++)
            for(int j=i+1;j<points.length;j++){
            Point p1 = points[i];
            Point p2 = points[j];
            if(p1.x!=p2.x && p1.y!=p2.y){
                double k=(p1.y-p2.y)*1.0/(p1.x-p2.x);
                double b= p1.y-k*p1.x;
                Line line = new Line(k,b);
                lineSet.add(line);
            }
            }

        for(Point p:points){
                for(Line line:lineSet){
                    // 如果点在直线上
                    if (Math.abs(p.y-line.k*p.x-line.b)<1e-9){
                        if(map.containsKey(line))
                            map.put(line,map.get(line)+1);
                        else
                            map.put(line,1);
                    }

                }
        }

        int res=0;
        for(Line l:map.keySet()){
            res=res>map.get(l)?res:map.get(l);
        }
        return res;
    }


}

class Point {
    int x,y;
    public Point(){

    }
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Point point = (Point) o;

        if (x != point.x) return false;
        return y == point.y;
    }

    @Override
    public int hashCode() {
        int result = x;
        result = 31 * result + y;
        return result;
    }
}

class Line{
    double k,b;

    public Line(double k, double b) {
        this.k = k;
        this.b = b;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Line line = (Line) o;

        if (Double.compare(line.k, k) != 0) return false;
        return Double.compare(line.b, b) == 0;
    }

    @Override
    public int hashCode() {
        int result;
        long temp;
        temp = Double.doubleToLongBits(k);
        result = (int) (temp ^ (temp >>> 32));
        temp = Double.doubleToLongBits(b);
        result = 31 * result + (int) (temp ^ (temp >>> 32));
        return result;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值