FastCollinearPoints 快速四点共线判断
一个人比较缓慢,大多数在于信息不全面、思维碰撞缺乏,在B站上也没有找到相关群体
故此,留一个群号,希望可以共同进步,相互监督,940774008
FastCollinearPoints.java
快速判断 四点共线模式
核心思想:利用 归并排序+插入排序的 Stable 特性 => SQL 的 字母排序分组group by+order by
先对所有的 points 按照 XY-coordinate 进行预排序,从小到大【左下角 左上角为小】
然后再对 除端点point以外的 otherPoints[] 根据 斜率排序【保存了上次的从小到大顺序】
这样,我们就能只关注两端的Point,不需要再记录中间的point,以免形成子线段。
import java.util.ArrayList;
import java.util.Arrays;
public class FastCollinearPoints {
private ArrayList<LineSegment> lineSegmentList;
// finds all line segments containing 4 or more points
public FastCollinearPoints(Point[] points) {
// 0.Check Exception
if (points == null)
throw new IllegalArgumentException();
for (int i = 0; i < points.length; i++) {
if (points[i] == null)
throw new IllegalArgumentException();
for (int j = i+1; j < points.length; j++) {
if (points[i].compareTo(points[j]) == 0)
throw new IllegalArgumentException();
}
}
Arrays.sort(points);
lineSegmentList = new ArrayList<LineSegment>();
Point[] other = new Point[points.length - 1];
for (int i = 0; i < points.length; i++) {
// assign current and other
Point current = points[i];
for (int t = 0; t < points.length; t++) {
if (t < i)
other[t] = points[t];
else if (t > i)
other[t - 1] = points[t];
}
// Sort by slope
Arrays.sort(other, current.slopeOrder());
int count = 2;
for (int j = 0; j < other.length - 1; j++) {
double k1 = current.slopeTo(other[j]);
double k2 = current.slopeTo(other[j + 1]);
if (k1 == k2) {
count++;
if (j == other.length - 2 && count >= 4) {
if (current.compareTo(other[j - count + 3]) < 0)
lineSegmentList.add(new LineSegment(current, other[other.length - 1]));
}
}
else {
if (count >= 4 && current.compareTo(other[j - count + 2]) < 0)
lineSegmentList.add(new LineSegment(current, other[j]));
count = 2;
}
}
}
}
// the number of line segments
public int numberOfSegments() {
return lineSegmentList.size();
}
// the line segments
public LineSegment[] segments() {
return lineSegmentList.toArray(new LineSegment[0]);
}
}
Point.java
/******************************************************************************
* Compilation: javac Point.java
* Execution: java Point
* Dependencies: none
*
* An immutable data type for points in the plane.
* For use on Coursera, Algorithms Part I programming assignment.
*
******************************************************************************/
import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.StdDraw;
import edu.princeton.cs.algs4.StdOut;
import java.util.Comparator;
public class Point implements Comparable<Point> {
private final int x; // x-coordinate of this point
private final int y; // y-coordinate of this point
/**
* Initializes a new point.
*
* @param x the <em>x</em>-coordinate of the point
* @param y the <em>y</em>-coordinate of the point
*/
public Point(int x, int y) {
/* DO NOT MODIFY */
this.x = x;
this.y = y;
}
/**
* Draws this point to standard draw.
*/
public void draw() {
/* DO NOT MODIFY */
StdDraw.point(x, y);
}
/**
* Draws the line segment between this point and the specified point
* to standard draw.
*
* @param that the other point
*/
public void drawTo(Point that) {
/* DO NOT MODIFY */
StdDraw.line(this.x, this.y, that.x, that.y);
}
/**
* Returns the slope between this point and the specified point.
* Formally, if the two points are (x0, y0) and (x1, y1), then the slope
* is (y1 - y0) / (x1 - x0). For completeness, the slope is defined to be
* +0.0 if the line segment connecting the two points is horizontal;
* Double.POSITIVE_INFINITY if the line segment is vertical;
* and Double.NEGATIVE_INFINITY if (x0, y0) and (x1, y1) are equal.
*
* @param that the other point
* @return the slope between this point and the specified point
*/
public double slopeTo(Point that) {
if (this.x == that.x && this.y == that.y) {
return Double.NEGATIVE_INFINITY;
}
if (this.y == that.y) {
return 0.0;
}
if (this.x == that.x) {
return Double.POSITIVE_INFINITY;
}
return (double) (that.y - this.y) / (that.x - this.x);
}
/**
* Compares two points by y-coordinate, breaking ties by x-coordinate.
* Formally, the invoking point (x0, y0) is less than the argument point
* (x1, y1) if and only if either y0 < y1 or if y0 = y1 and x0 < x1.
*
* @param that the other point
* @return the value <tt>0</tt> if this point is equal to the argument
* point (x0 = x1 and y0 = y1);
* a negative integer if this point is less than the argument
* point; and a positive integer if this point is greater than the
* argument point
*/
public int compareTo(Point that) {
/* YOUR CODE HERE */
// 原要求:如果当前点在参数点的左下 则返回 -1
// 但为了 当斜率 k 为负数时,也能保证 反斜线的点们有序 故 左上也返回-1
// 为此这里会造成 Testing correctness of Point API compareTo 方法的测试失败
if (this.x == that.x && this.y == that.y) {
return 0;
}
else if (this.y <= that.y && this.x < that.x || this.y >= that.y && this.x < that.x) {
return -1;
}
else
return 1;
}
/**
* Compares two points by the slope they make with this point.
* The slope is defined as in the slopeTo() method.
*
* @return the Comparator that defines this ordering on points
*/
public Comparator<Point> slopeOrder() {
/* YOUR CODE HERE */
return new MyComparator();
}
private class MyComparator implements Comparator<Point> {
public int compare(Point t1, Point t2) {
return Double.compare(slopeTo(t1), slopeTo(t2));
}
}
/**
* Returns a string representation of this point.
* This method is provide for debugging;
* your program should not rely on the format of the string representation.
*
* @return a string representation of this point
*/
public String toString() {
/* DO NOT MODIFY */
return "(" + x + ", " + y + ")";
}
/**
* Unit tests the Point data type.
*/
public static void main(String[] args) {
/* YOUR CODE HERE */
// read the n points from a file
In in = new In(args[0]);
int n = in.readInt();
Point[] points = new Point[n];
for (int i = 0; i < n; i++) {
int x = in.readInt();
int y = in.readInt();
points[i] = new Point(x, y);
}
// draw the points
StdDraw.enableDoubleBuffering();
StdDraw.setXscale(0, 32768);
StdDraw.setYscale(0, 32768);
for (Point p : points) {
p.draw();
}
StdDraw.show();
// print and draw the line segments
// BruteCollinearPoints collinear = new BruteCollinearPoints(points);
FastCollinearPoints collinear = new FastCollinearPoints(points);
for (LineSegment segment : collinear.segments()) {
StdOut.println(segment);
segment.draw();
}
StdDraw.show();
}
}
BruteCollinearPoints.java
这里也有没想通的地方:Arrays.sort (points, tmp.slopeOrder() ? 与 null ?)
为什么以null 比较器的情况成功,而使用 slopeOrder()返回的比较器失败。
因为,这里的原理是 不去重 子线段,一定会画出完整的长线段。就有点迷。欢迎各位解惑
import java.util.ArrayList;
import java.util.Arrays;
public class BruteCollinearPoints {
private ArrayList<LineSegment> lineSegmentList;
// finds all line segments containing 4 points
public BruteCollinearPoints(Point[] points) {
// 0.Check Exception
if (points == null)
throw new IllegalArgumentException();
for (int i = 0; i < points.length; i++) {
if (points[i] == null)
throw new IllegalArgumentException();
for (int j = i+1; j < points.length; j++) {
if (points[i].compareTo(points[j]) == 0)
throw new IllegalArgumentException();
}
}
Point[] usePoints = Arrays.copyOf(points, points.length);
Arrays.sort(usePoints);
lineSegmentList = new ArrayList<LineSegment>();
for (int i = 0; i < usePoints.length - 3; i++) {
for (int j = i + 1; j < usePoints.length - 2; j++) {
double k12 = usePoints[i].slopeTo(usePoints[j]);
for (int k = j + 1; k < usePoints.length - 1; k++) {
double k13 = usePoints[i].slopeTo(usePoints[k]);
if (k12 != k13)
continue;
for (int m = k + 1; m < usePoints.length; m++) {
double k14 = usePoints[i].slopeTo(usePoints[m]);
if (k12 != k14)
continue;
lineSegmentList.add(new LineSegment(usePoints[i], usePoints[m]));
}
}
}
}
}
// the number of line segments
public int numberOfSegments() {
return lineSegmentList.size();
}
// the line segments
public LineSegment[] segments() {
return lineSegmentList.toArray(new LineSegment[0]);
}
}
评分
过关为主,不细究评分
See the Assessment Guide for information on how to interpret this report.
ASSESSMENT SUMMARY
Compilation: PASSED
API: PASSED
Spotbugs: FAILED (4 warnings)
PMD: FAILED (2 warnings)
Checkstyle: PASSED
Correctness: 37/41 tests passed
Memory: 1/1 tests passed
Timing: 41/41 tests passed
Aggregate score: 94.15%
[Compilation: 5%, API: 5%, Spotbugs: 0%, PMD: 0%, Checkstyle: 0%, Correctness: 60%, Memory: 10%, Timing: 20%]

658

被折叠的 条评论
为什么被折叠?



