Finding the maximum number of points lying on the same line in a two-dimensional plane

This is "Given n points on a two-dimensional plane, find the maximum number of points lying on one straight line." question from leetcode.com I am trying to resolve it, but I cannot pass all the test cases.

What I'm trying to do is: - I use hashmap, whose key is the angle b / w, which I get through tan, inverse of the slope, and I save the values ​​for each slope initially the value is not the origin of this point, and then it increase.

I use a different hash map to count the availability of points.

I do not get the correct answer for points like (0,0), (1,0), which should return 2 but return 1.

What am I missing?

My code is:

public class MaxPointsINLine { int max = 0; int same; public int maxPoints(Point[] points) { int max = 0; Map<Double, Integer> map = new HashMap<Double, Integer>(); Map<Point, Integer> pointmap = new HashMap<Point, Integer>(); for(Point point: points) { if(!pointmap.containsKey(point)) { pointmap.put(point, 1); } else { pointmap.put(point, pointmap.get(point)+1); } } if (points.length >= 2) { for (int i = 0; i < points.length; i++) { for (int j = i ; j < points.length; j++) { double dx = points[j].x - points[i].x; double dy = points[j].y - points[i].y; double slope = Math.atan(dy / dx); if (!map.containsKey(slope)) { map.put(slope, pointmap.get(points[j])); } else map.put(slope, map.get(slope) + 1); } } for (Double key : map.keySet()) { if (map.get(key) > max) { max = map.get(key); } } return max; } else if (points.length != 0) { return 1; } else { return 0; } } public static void main(String[] args) { Point point1 = new Point(0,0); Point point2 = new Point(0,0); //Point point3 = new Point(2,2); MaxPointsINLine maxpoint = new MaxPointsINLine(); Point[] points = { point1, point2}; System.out.println(maxpoint.maxPoints(points)); } } class Point { int x; int y; Point() { x = 0; y = 0; } Point(int a, int b) { x = a; y = b; } @Override public boolean equals(Object obj) { Point that = (Point)obj; if (that.x == this.x && that.y == this.y) return true; else return false; } @Override public int hashCode() { // TODO Auto-generated method stub return 1; } } 
+5
source share
3 answers

The overall strategy does not seem to work. Suppose we successfully populated map with key-value pairs (a, N) , where a is the angle and N is the number of pairs of points connected by the angle a . Consider the following 6-point diagram:

 ** ** ** 

Obviously, there are points in (0,0), (1,0), (2,1), (3,1), (0,2) and (1,2). You can check that the maximum number of points lying on any line is 2. However, there are three pairs of points that are connected by the same angle: ((0,0), (1,0)), ((2, 1 ), (3.1)) and ((0.2), (1.2)). Thus, map will contain a key-value pair with N = 3 , but this is not the answer to the original question.

Due to devices like the above, tilt counting is not enough. A successful algorithm should present strings so that you can distinguish between parallel lines.

+2
source

The simplest solution here is as follows: you can consider each pair of points. For each pair, one calculates the distance of each other point to the line connecting the two points. If this distance is almost zero, then the point lies on a straight line.

When this is done for all pairs, you can select the pair for which the largest number of points lies on the connecting line.

Of course, this is not very elegant, since it is in O (n ^ 3) and performs some calculations twice. But it is very simple and reliable enough. I just implemented this as MCVE here:

PointsOnLine

You can set points by left-clicking. Right clicks clear the screen. The maximum number of points in one line is displayed, and the corresponding points are highlighted.

(UPDATE: updated to handle points that have a distance of 0, based on a comment)

 import java.awt.BorderLayout; import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.geom.Line2D; import java.util.ArrayList; import java.util.List; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingUtilities; public class PointsOnStraightLineTest { public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { createAndShowGUI(); } }); } private static void createAndShowGUI() { JFrame f = new JFrame(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.getContentPane().setLayout(new BorderLayout()); f.getContentPane().add(new PointsPanel()); f.setSize(600, 600); f.setLocationRelativeTo(null); f.setVisible(true); } } class PointsOnStraightLine { // Large epsilon to make it easier to place // some points on one line with the mouse... private static final double EPSILON = 5.0; List<Point> maxPointsOnLine = new ArrayList<Point>(); void compute(List<Point> points) { maxPointsOnLine = new ArrayList<Point>(); for (int i=0; i<points.size(); i++) { for (int j=i+1; j<points.size(); j++) { Point p0 = points.get(i); Point p1 = points.get(j); List<Point> resultPoints = null; if (p0.distanceSq(p1) < EPSILON) { resultPoints = computePointsNearby(p0, points); } else { resultPoints = computePointsOnLine(p0, p1, points); } if (resultPoints.size() > maxPointsOnLine.size()) { maxPointsOnLine = resultPoints; } } } } private List<Point> computePointsOnLine( Point p0, Point p1, List<Point> points) { List<Point> result = new ArrayList<Point>(); for (int k=0; k<points.size(); k++) { Point p = points.get(k); double d = Line2D.ptLineDistSq(p0.x, p0.y, p1.x, p1.y, px, py); if (d < EPSILON) { result.add(p); } } return result; } private List<Point> computePointsNearby( Point p0, List<Point> points) { List<Point> result = new ArrayList<Point>(); for (int k=0; k<points.size(); k++) { Point p = points.get(k); double d = p.distanceSq(p0); if (d < EPSILON) { result.add(p); } } return result; } } class PointsPanel extends JPanel implements MouseListener { private final List<Point> points; private final PointsOnStraightLine pointsOnStraightLine; PointsPanel() { addMouseListener(this); points = new ArrayList<Point>(); pointsOnStraightLine = new PointsOnStraightLine(); } @Override protected void paintComponent(Graphics gr) { super.paintComponent(gr); Graphics2D g = (Graphics2D)gr; g.setColor(Color.BLACK); for (Point p : points) { g.fillOval(px-2, py-2, 4, 4); } pointsOnStraightLine.compute(points); int n = pointsOnStraightLine.maxPointsOnLine.size(); g.drawString("maxPoints: "+n, 10, 20); g.setColor(Color.RED); for (Point p : pointsOnStraightLine.maxPointsOnLine) { g.drawOval(px-3, py-3, 6, 6); } } @Override public void mouseClicked(MouseEvent e) { if (SwingUtilities.isRightMouseButton(e)) { points.clear(); } else { points.add(e.getPoint()); } repaint(); } @Override public void mousePressed(MouseEvent e) { } @Override public void mouseReleased(MouseEvent e) { } @Override public void mouseEntered(MouseEvent e) { } @Override public void mouseExited(MouseEvent e) { } } 
+2
source

This worked for me:

 /** * 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 { public int maxPoints(Point[] points) { int result = 0; for(int i = 0; i<points.length; i++){ Map<Double, Integer> line = new HashMap<Double, Integer>(); Point a = points[i]; int same = 1; //System.out.println(a); for(int j = i+1; j<points.length; j++){ Point b = points[j]; //System.out.println(" point " + b.toString()); if(ax == bx && ay == by){ same++; } else { double dy = by - ay; double dx = bx - ax; Double slope; if(dy == 0){ // horizontal slope = 0.0; } else if(dx == 0){//eartical slope = Math.PI/2; } else { slope = Math.atan(dy/dx); } Integer slopeVal = line.get(slope); //System.out.println(" slope " + slope + " slope value " + slopeVal); if(slopeVal == null){ slopeVal = 1; } else { slopeVal += 1; } line.put(slope, slopeVal); } } for (Double key : line.keySet()) { Integer val = line.get(key); result = Math.max(result, val + same); } // for all points are same result = Math.max(result, same); } return result; } } 
+2
source

Source: https://habr.com/ru/post/1200483/


All Articles