普林斯顿算法课第三周作业
来源:互联网 发布:pos机软件 编辑:程序博客网 时间:2024/06/05 01:58
第三周作业模式识别
Programming Assignment 3: Pattern Recognition
题目地址:http://coursera.cs.princeton.edu/algs4/assignments/collinear.html
------------------------------------------
这一周的问题是在一个给出N个随即点的平面上,画出所有所在路径超过四个点的直线。
首先还是老老实实的从第一个类开始说起。
public class Point implements Comparable<Point> { public final Comparator<Point> SLOPE_ORDER; // compare points by slope to this point public Point(int x, int y) // construct the point (x, y) public void draw() // draw this point public void drawTo(Point that) // draw the line segment from this point to that point public String toString() // string representation public int compareTo(Point that) // is this point lexicographically smaller than that point? public double slopeTo(Point that) // the slope between this point and that point}
第一个类的主要功能是创建点的分布,并通过StdDraw类输出,其中运用到了比较器。
很良心的,其中前四个方法已经给出。
我们只需要把后两个和比较器写出。
1. public int compareTo(Point that) // is this point lexicographically smaller than that point?
也就是是否这个点是否比那个点小,比较标准给出了,
y0<y1或y0=y1但x0<x1时 表示this.point<that.point
2.public double slopeTo(Point that) // the slope between this point and that point
计算两点间斜率,官方说明上给的很清楚,包括各类情况的返回值,就不多说了。
3.public final Comparator<Point> SLOPE_ORDER;
用来比较斜率的比较器,第一次用不是很会用。后来摸透了以后感觉很方便。
代码如下:
import java.util.Comparator;public class Point implements Comparable<Point> { // compare points by slope public final Comparator<Point> SLOPE_ORDER= new SlopeOrder();; // YOUR DEFINITION HERE private final int x; // x coordinate private final int y; // y coordinate private class SlopeOrder implements Comparator<Point>{ public int compare(Point p1, Point p2) { double slopeP1 = slopeTo(p1); double slopeP2 = slopeTo(p2); if (slopeP1 == slopeP2) return 0; if (slopeP1 < slopeP2) return -1; else return +1; } } // create the point (x, y) public Point(int x, int y) { /* DO NOT MODIFY */ this.x = x; this.y = y; } // plot this point to standard drawing public void draw() { /* DO NOT MODIFY */ StdDraw.point(x, y); } // draw line between this point and that point to standard drawing public void drawTo(Point that) { /* DO NOT MODIFY */ StdDraw.line(this.x, this.y, that.x, that.y); } // slope between this point and that point public double slopeTo(Point that) { /* YOUR CODE HERE */ if (this.compareTo(that) == 0) return Double.NEGATIVE_INFINITY; else if (this.x == that.x) return Double.POSITIVE_INFINITY; else if (this.y == that.y) return +0; else return (that.y - this.y) * 1.0 / (that.x - this.x); } // is this point lexicographically smaller than that one? // comparing y-coordinates and breaking ties by x-coordinates public int compareTo(Point that) { /* YOUR CODE HERE */ if (this.y < that.y || (this.y == that.y && this.x < that.x)) return -1; else if (this.y == that.y && this.x == that.x) return 0; else return 1; } // return string representation of this point public String toString() { /* DO NOT MODIFY */ return "(" + x + ", " + y + ")"; } // unit test public static void main(String[] args) { // rescale coordinates and turn on animation mode StdDraw.setXscale(0, 32768); StdDraw.setYscale(0, 32768); StdDraw.show(0); StdDraw.setPenRadius(0.01); // make the points a bit larger // read in the input String filename = args[0]; In in = new In(filename); int N = in.readInt(); for (int i = 0; i < N; i++) { int x = in.readInt(); int y = in.readInt(); Point p = new Point(x, y); p.draw(); } // display to screen all at once StdDraw.show(0); // reset the pen radius StdDraw.setPenRadius(); }}
第二个类是用暴力方法连线
暴力解法的思想很简单,用枚举法对所有点进行排序后判断斜率,三个斜率相等后则画出直线。
当然时间很慢,复杂度是N^4
代码如下:
public class Brute {public static void main(String[] args) { // rescale coordinates and turn on animation mode StdDraw.setXscale(0, 32768); StdDraw.setYscale(0, 32768); // read in the input String filename = args[0]; In in = new In(filename); int N = in.readInt(); Point[] pointArray=new Point[N]; for (int i = 0; i < N; i++) { int x = in.readInt(); int y = in.readInt(); Point p = new Point(x, y); pointArray[i] = p; p.draw(); } Quick3way.sort(pointArray); BruteForce(pointArray); StdDraw.show(0); }private static void BruteForce(Point[] pointArray){ int N = pointArray.length; for (int i=0; i<N; i++){ for (int j=i+1; j<N; j++){ for (int k=j+1; k<N; k++){ for (int l=k+1; l<N; l++){ if (pointArray[i].slopeTo(pointArray[j]) == pointArray[i].slopeTo(pointArray[k]) && pointArray[i].slopeTo(pointArray[j]) == pointArray[i].slopeTo(pointArray[l])){ StdOut.println(pointArray[i] + " -> " + pointArray[j] + " -> " + pointArray[k] + " -> " + pointArray[l]); pointArray[i].drawTo(pointArray[l]); } } } } } } }
第三个类是用一个很快的、基于排序的解决方法。
在给定点P上,对所有斜率进行排序,如果存在三个点或以上的斜率相等,则共线。
当然还是要枚举P点,不过排序的话复杂度会下降很多。
同时要避免同一条线段多次输出,需要用到compareTo。
代码如下:
import java.util.Arrays;public class Fast {public static void main(String[] args){// rescale coordinates and turn on animation mode StdDraw.setXscale(0, 32768); StdDraw.setYscale(0, 32768); String filename = args[0]; In in = new In(filename); int N = in.readInt(); if (N < 4){ return; } Point[] pointArray = new Point[N]; for (int i = 0; i < N; i++) { int x = in.readInt(); int y = in.readInt(); Point p = new Point(x, y); pointArray[i] = p; p.draw(); } Quick3way.sort(pointArray); FastMethod(pointArray); StdDraw.show(0); }private static void FastMethod(Point[] pointArray){int N = pointArray.length;for (int i=0; i<N; i++){Point origPoint = pointArray[i];Point[] otherPoint = new Point[N-1];for (int j=0; j<pointArray.length; j++){if (j < i) otherPoint[j] = pointArray[j];if (j > i) otherPoint[j-1] = pointArray[j];}Arrays.sort(otherPoint, origPoint.SLOPE_ORDER);int count = 0;int index = 0;double tempSlope = origPoint.slopeTo(otherPoint[0]);for (int j=0; j<otherPoint.length;j++){if (Double.compare(origPoint.slopeTo(otherPoint[j]), tempSlope) == 0){count++;continue;}else{if (count >=3){if (otherPoint[index].compareTo(origPoint) >=0){StdOut.print(origPoint + " -> ");for (int k=index; k<j-1; k++){StdOut.print(otherPoint[k] + " -> ");}StdOut.println(otherPoint[j-1]);origPoint.drawTo(otherPoint[j-1]);}}count = 1;index = j;tempSlope = origPoint.slopeTo(otherPoint[j]);}}if (count >= 3){if (otherPoint[index].compareTo(origPoint) >= 0){StdOut.print(origPoint + " -> ");for (int k=index; k<otherPoint.length - 1; k++){StdOut.print(otherPoint[k] + " -> ");}StdOut.println(otherPoint[otherPoint.length-1]);origPoint.drawTo(otherPoint[otherPoint.length-1]);}}}StdDraw.show(0);}}
0 0
- 普林斯顿算法课第三周作业
- 普林斯顿算法课第五周作业
- 普林斯顿算法课第二周作业
- 普林斯顿算法课第一周作业
- 普林斯顿算法课第四周作业
- Coursera普林斯顿大学算法课-编程作业1: Percolation
- 普林斯顿大学算法课程第三周个人总结
- 第三周算法作业
- 算法课第三周作业 | Subsets
- 算法概论第三周作业
- 第三周作业 算法概论
- 算法第三周作业02
- 算法第三周作业01
- 算法第三周作业03
- 普林斯顿公开课 算法1-2:观察
- 普林斯顿公开课 算法1-3:数学模型
- 普林斯顿公开课 算法1-6:内存
- 普林斯顿公开课 算法2-7:栈
- 层序遍历二叉树,以及拓展问题,同层同行输出
- 兔子--android自动化框架及其特点
- 黑马程序员---设计模式之工厂模式
- 【机器学习中的数学】比例混合分布
- 工作杂谈:产品经理与项目经理
- 普林斯顿算法课第三周作业
- CentOS 7.0 + JBOSS 7.1.1 相关命令行
- JSP--JSP语法
- Managing Bitmap Memory
- wget 详细介绍
- 轮子----文本框内容不是唯一返回
- 换不开的硬币问题
- uri、url、refer
- 学习angular ui-router - 管理状态