最痛苦的一周——第三周作业Collinear

这个作业已经有点儿久远了,但是给我留下了很深的印象。这五周的作业中,就这个最困难了。自己真的花了两天时间在这次作业上面。最后解题思路还是在Coursera讨论上看到的。
brute-force解法就不多说了,但还是踩了一些坑。
重点在FastCollinear的实现,回过头来发现只有一百多行代码真的不敢置信。这次作业是对sort的应用。按每个点和其它点形成的斜率,然后排序。所以如果有四点在一个线上,非常容易寻找。但是最困的是找出重复的线段和子线段。在论坛找到的思路是遍历按斜率排序好的队列,将几个相同的放到Stack中,将保存到Stack中的同线点排序,于是就找出并保存了最大线段。
还有一个坑是,因为循环写法的原因,这个点的判断在下一次加入到队列中。所以最后一个点没有加入进去。而垂直的线斜率最大,正好排在最后。因此所有垂直的线丢没有找出来。
BruteCollinearPoints.java
···
import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.StdDraw;
import edu.princeton.cs.algs4.StdOut;

import java.util.Arrays;

public class BruteCollinearPoints {

private LineSegment[] segments;
private int endpoint;
private int nsegments;

public BruteCollinearPoints(Point[] pointss) {
if(pointss == null)
throw new IllegalArgumentException();
for(int i=0; i<pointss.length; i++) {
if(pointss[i] == null)
throw new IllegalArgumentException();
}
for(int i=0; i<pointss.length; i++) {
for(int j=0; j<pointss.length; j++) {
if(i == j)
continue;
if(pointss[i].slopeTo(pointss[j]) == Double.NEGATIVE_INFINITY)
throw new IllegalArgumentException();
}
}
Point[] points = new Point[pointss.length];
for(int i=0;i<points.length;i++) {
points[i] = pointss[i];
}
Arrays.sort(points);
segments = new LineSegment[points.length];
endpoint = points.length - 1;
try {
outer:
for(int p=0; p<points.length; p++) {
for(int q=endpoint; q>p; q--) {
double pq = points[p].slopeTo(points[q]);
for(int r=q-1; r>p; r--) {
double qr = points[q].slopeTo(points[r]);
if(qr == pq)
for(int s=r-1; s>p; s--) {
double rs = points[r].slopeTo(points[s]);
if(qr == rs) {
segments[nsegments++] = new LineSegment(points[p], points[q]);
//continue outer;
}
}
}
}

}
} catch (NullPointerException e) {
throw new IllegalArgumentException();
}
}
public int numberOfSegments() {
return nsegments;
}
public LineSegment[] segments() {
LineSegment[] lineSegements = new LineSegment[nsegments];
for(int i=0; i<nsegments; i++) {
lineSegements[i] = segments[i];
}
return lineSegements;
}

public static void main(String[] args) {
// 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);
for (LineSegment segment : collinear.segments()) {
StdOut.println(segment);
segment.draw();
}
StdDraw.show();
}
}

···
FastCollinearPoints.java

import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.StdDraw;
import edu.princeton.cs.algs4.StdOut;

import java.util.Arrays;

public class BruteCollinearPoints {

    private LineSegment[] segments;
    private int endpoint;
    private int nsegments;

    public BruteCollinearPoints(Point[] pointss) {
        if(pointss == null)
            throw new IllegalArgumentException();
        for(int i=0; i<pointss.length; i++) {
            if(pointss[i] == null)
                throw new IllegalArgumentException();
        }
        for(int i=0; i<pointss.length; i++) {
            for(int j=0; j<pointss.length; j++) {
                if(i == j)
                    continue;
                if(pointss[i].slopeTo(pointss[j]) == Double.NEGATIVE_INFINITY)
                    throw new IllegalArgumentException();
            }
        }
        Point[] points = new Point[pointss.length];
        for(int i=0;i<points.length;i++) {
            points[i] = pointss[i];
        }
        Arrays.sort(points);
        segments = new LineSegment[points.length];
        endpoint = points.length - 1;
        try {
            outer:
            for(int p=0; p<points.length; p++) {
                for(int q=endpoint; q>p; q--) {
                    double pq = points[p].slopeTo(points[q]);
                    for(int r=q-1; r>p; r--) {
                        double qr = points[q].slopeTo(points[r]);
                        if(qr == pq)
                        for(int s=r-1; s>p; s--) {
                            double rs = points[r].slopeTo(points[s]);
                            if(qr == rs) {
                                segments[nsegments++] = new LineSegment(points[p], points[q]);
                                //continue outer;
                            }
                        }
                    }
                }

             }
        } catch (NullPointerException e) {
            throw new IllegalArgumentException();
        }
    }
    public int numberOfSegments() {
        return nsegments;
    }
    public LineSegment[] segments() {
        LineSegment[] lineSegements = new LineSegment[nsegments];
        for(int i=0; i<nsegments; i++) {
            lineSegements[i] = segments[i];
        }
        return lineSegements;
    }

    public static void main(String[] args) {
        // 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);
        for (LineSegment segment : collinear.segments()) {
            StdOut.println(segment);
            segment.draw();
        }
        StdDraw.show();
    }
}

posted @ 2018-03-05 09:34  新月的力量_141  阅读(717)  评论(0)    收藏  举报