149、Max Points on a Line (Hard)

Given n points on a 2D plane, find the maximum number of points that lie on the same straight line.

题目就是在二维平面里给一堆点的x坐标和y坐标,求一条能穿过点的直线的上面的点的最大数目。

题意很明确,难点在于一是用何种数据结构解决,二是如何区分直线。因为每个直线有k和b两个属性,而两点共线说明y1=kx1+b,y2=kx2+b,所以可以用k=(y2-y1)/(x2-x1)这个数字来唯一区分直线,注意这里把b消除了,其实加上b也没事,因为用k和b区分和只用k区分是一样的。那么考虑到直线的唯一性问题,用HashMap实现就显而易见了(这个题自己思路正确了,但是由于程序的实现没有考虑到两个点完全重合的情况,所以修改实现流程的逻辑判断花了很长时间)。


import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.Set;

public class Test {
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int number = in.nextInt();
		Point[] p = new Point[number];
		for (int i = 0; i < number; i++) {
			int a = in.nextInt();
			int b = in.nextInt();
			p[i] = new Point(a, b);
		}
		System.out.println(maxPoints(p));
	}

	public static int maxPoints(Point[] points) {		
		if (points.length < 3) {
			return points.length;
		}

		HashMap<Integer, Integer> xmap = new HashMap<Integer, Integer>();
		HashMap<String, Integer> xymap = new HashMap<String, Integer>();
		int x = 0;
		int y = 0;
		int x1 = 0;
		int y1 = 0;
		int xcount = 1;
		int xycount = 1;
		for (int i = 0; i < points.length; i++) {
			x = points[i].x;
			y = points[i].y;
			String s = x + "," + y;
			if (xmap.get(x) != null) {
				xcount = xmap.get(x) + 1;
			}
			xmap.put(x, xcount);
		}
		
		int result = 0;
		
		for (int i = 0; i < points.length-1; i++) {
			xymap.clear();
			x = points[i].x;
			y = points[i].y;
			int flag = 0;
			int max = 0;
			for (int j = i + 1; j < points.length; j++) {
				xycount = 1;
				x1 = points[j].x;
				y1 = points[j].y;
				if (x1 - x == 0) {
					if (y1 - y == 0) {
						flag++;
						continue;
					}
					
				}
				int gcd = getMaxGCD(x1 - x, y1 - y);
				System.out.println("gcd:"+gcd);
				String s = ((y1 - y) / gcd) + "/" + ((x1 - x) / gcd); 
				if (xymap.get(s) != null) {
					xycount = xymap.get(s) + 1;
				}
				xymap.put(s, xycount);				
				max = Math.max(max,xycount);
			}
			result = Math.max(result, max+flag+1);
		}
		Set<Entry<Integer, Integer>> entrySetx = xmap.entrySet();
		xcount = 1;
		for (Entry<Integer, Integer> entry : entrySetx) {
			if (entry.getValue() > xcount) {
				xcount = entry.getValue();
			}
		}
		System.out.println("xcount"+xcount);
		System.out.println("result"+result);
		return xcount > result ? xcount : result;
	
	}

	public static int getMaxGCD(int x, int y) {
		if (y == 0) {
			return x;
		} else {
			return getMaxGCD(y, x % y);
		}
	}

	public static int getNumber(int x) {
		int number = (int) Math.sqrt(x);
		if (number * number > x) {
			for (int i = number; i >= 0; i--) {
				if (i * (i - 1) / 2 == x) {
					return i;
				}
			}
		} else {
			for (int i = number; i <= x; i++) {
				if (i * (i - 1) / 2 == x) {
					return i;
				}
			}
		}
		return 0;
	}
		
		/*
       	if (points==null) return 0;
    	if (points.length<=2) return points.length;
    	
    	Map<Integer,Map<Integer,Integer>> map = new HashMap<Integer,Map<Integer,Integer>>();
    	int result=0;
    	for (int i=0;i<points.length;i++){ 
    		map.clear();
    		int overlap=0,max=0;
    		for (int j=i+1;j<points.length;j++){
    			int x=points[j].x-points[i].x;
    			int y=points[j].y-points[i].y;
    			System.out.println("i:"+i+"  x:"+x+"  y:"+y);
    			if (x==0&&y==0){
    				overlap++;
    				continue;
    			}
    			int gcd=generateGCD(x,y);
    			System.out.println("gcd:"+gcd);
    			if (gcd!=0){
    				x/=gcd;
    				y/=gcd;
    			}
    			
    			if (map.containsKey(x)){
    				if (map.get(x).containsKey(y)){
    					map.get(x).put(y, map.get(x).get(y)+1);
    				}else{
    					map.get(x).put(y, 1);
    				}   					
    			}else{
    				Map<Integer,Integer> m = new HashMap<Integer,Integer>();
    				m.put(y, 1);
    				map.put(x, m);
    			}
    			max=Math.max(max, map.get(x).get(y));
    		}
    		result=Math.max(result, max+overlap+1);
    	}
    	return result;
    	
	}
	
	public static int generateGCD(int x, int y) {
		if (y == 0) {
			return x;
		} else {
			return generateGCD(y, x % y);
		}
	}
	*/
}

class Point {
	int x;
	int y;

	Point() {
		x = 0;
		y = 0;
	}

	Point(int a, int b) {
		x = a;
		y = b;
	}
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值