【Coursera】编程题 Collinear Points
来源:互联网 发布:2016网络神曲排行榜 编辑:程序博客网 时间:2024/04/20 01:30
题目概述:http://coursera.cs.princeton.edu/algs4/assignments/collinear.html
Point类和暴力算法(O(n^4))都很简单,就不写了。
写一个把复杂度降到n^2lg(n)的算法。
感觉写出来的东西很混乱。。
import java.util.ArrayList;import java.util.Arrays;import edu.princeton.cs.algs4.Quick3way;import edu.princeton.cs.algs4.StdDraw;import edu.princeton.cs.algs4.StdIn;import edu.princeton.cs.algs4.StdOut;public class FastCollinearPoints { private int num = 0; // number of lines private ArrayList<LineSegment> al = null; public FastCollinearPoints(Point[] points) { if (points == null) throw new NullPointerException(); Point[] points1 = new Point[points.length]; System.arraycopy(points, 0, points1, 0, points.length); al = new ArrayList<LineSegment>(); Quick3way.sort(points1); // 保证所有点都在前一个点的右上方。 findDuplicate(points1); // 去除重复点 , 因为算法本身复杂度较高,加 一个线性复杂度的方法。。无所谓了。。 for (int i = 0; i < points1.length - 3; i++) { // 保留最后3个,加上originPoint,正好构成一个4个点的,后面的再遍历也没意义了,还会诱发NullPointerException if (points1[i] == null) throw new NullPointerException(); Point[] otherPoints = new Point[points1.length - 1]; // 除了originPoint ,其它点都在这里 Point originPoint = points1[i]; // 从这点画出连接其它点的射线 for (int j = 0, k = 0; k < otherPoints.length; j++, k++) { // initialize otherPoints[] if (points1[j] == null) throw new NullPointerException(); if (j < i) otherPoints[k] = points1[j]; else if (j == i) k--; else otherPoints[k] = points1[j]; } Arrays.sort(otherPoints, originPoint.slopeOrder()); // 按照斜率排序 int tempNum = 1; // 相同斜率的线条数,一开始肯定有一条,凑够3条就有4个点了,源点 + 3。 double tempSlope = originPoint.slopeTo(otherPoints[0]); for (int j = 1; j < otherPoints.length; j++) { if (Double.compare(tempSlope, originPoint.slopeTo(otherPoints[j])) != 0) { if (tempNum >= 3) { Point[] temp = new Point[tempNum + 1]; // 把能组成直线的点放到temp里面 temp[0] = originPoint; // put originPoint into temp[0] for (int k = 1; k <= tempNum; k++) { temp[k] = otherPoints[j - k]; } int indexOfMin = findMin(temp); // 找出最小的点,也就是源点 if (temp[indexOfMin] == originPoint) { // 如果最小点不是源点,就说明这个条线之前已经统计过了,直接跳过。 Point head = temp[indexOfMin], tail = temp[indexOfMin]; // 找到头尾 for (int l = 1; l < temp.length; l++) { if (temp[l].compareTo(head) < 0) head = temp[l]; if (temp[l].compareTo(tail) > 0) tail = temp[l]; } al.add(new LineSegment(head, tail)); num++; } } tempNum = 1; // 还原初始条件,并重设斜率 tempSlope = originPoint.slopeTo(otherPoints[j]); } else { tempNum++; } } if (tempNum >= 3) { // 防止末尾的直线没计入,可能最后斜率没变化就默默结束了 Point[] temp = new Point[tempNum + 1]; // 把能组成直线的点放到temp里面 temp[0] = originPoint; // put originPoint into temp[0] for (int k = 0; k < tempNum; k++) { temp[k + 1] = otherPoints[otherPoints.length -1 - k]; } int indexOfMin = findMin(temp); if (temp[indexOfMin] == originPoint) { Point head = temp[indexOfMin], tail = temp[indexOfMin]; // 找到头尾 for (int l = 1; l < temp.length; l++) { if (temp[l].compareTo(head) < 0) head = temp[l]; if (temp[l].compareTo(tail) > 0) tail = temp[l]; } al.add(new LineSegment(head, tail)); num++; } } } } /** * 寻找最小点 */ private int findMin(Point[] temp) { int index = 0; Point a = temp[0]; for (int i = 1; i < temp.length; i++) { if (a.compareTo(temp[i]) > 0) { a = temp[i]; index = i; } } return index; } /** * 排除重复 */ private void findDuplicate(Point[] points1) { for (int i = 0; i < points1.length - 1; i++) { if (points1[i].compareTo(points1[i + 1]) == 0) throw new IllegalArgumentException(); } } public int numberOfSegments() { // the number of line segments return num; } public LineSegment[] segments() { return al.toArray(new LineSegment[num]); } public static void main(String[] args) { // read the n points from a file int n = StdIn.readInt(); Point[] points = new Point[n]; for (int i = 0; i < n; i++) { int x = StdIn.readInt(); int y = StdIn.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 FastCollinearPoints collinear = new FastCollinearPoints(points); StdOut.println(collinear.segments().length); for (LineSegment segment : collinear.segments()) { StdOut.println(segment); segment.draw(); } StdDraw.show(); }}
还是把point也放进来,方便看。。
import java.util.Comparator;import edu.princeton.cs.algs4.StdDraw;public class Point implements Comparable<Point> { private final int x; // x-coordinate of this point private final int y; // y-coordinate of this point public Point(int x, int y) { if (x < 0 || x > 32767 || y < 0 || y > 32767) throw new IllegalArgumentException(); this.x = x; this.y = y; } /** * Draws this point to standard draw. */ public void draw() { 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) { 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.compareTo(that) == 0) return Double.NEGATIVE_INFINITY; // Same pint else if (this.x == that.x) return Double.POSITIVE_INFINITY; // Vertical else if (this.y == that.y) return +0.0; // Horizontal else return (that.y - this.y) * 1.0 / (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) { if (this.y > that.y) return 1; else if (this.y < that.y) return -1; else if (this.y == that.y && this.x > that.x) return 1; else if (this.y == that.y && this.x < that.x) return -1; else return 0; } /** * 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() { return new SlopeOrder(); } private class SlopeOrder implements Comparator<Point> { public int compare(Point p1, Point p2) { double slope1 = slopeTo(p1); double slope2 = slopeTo(p2); return Double.compare(slope1, slope2); } } /** * 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() { return "(" + x + ", " + y + ")"; } /** * Unit tests the Point data type. */ public static void main(String[] args) { /* YOUR CODE HERE */ }}
0 0
- 【Coursera】编程题 Collinear Points
- Programming Assignment: Collinear Points
- 【Coursera】编程题 Percolation
- Coursera
- coursera
- Coursera
- Coursera pku C程序进阶 编程题#4:扩号匹配问题
- Coursera 编程题 #3 运算符重载 写一个二维数组类 Array2心得
- coursera Python交互编程入门 习题答案
- 【Coursera公开课】计算机程序设计 编程作业
- Coursera机器学习 week6 编程作业代码
- Coursera公开课-Machine_learing:编程作业
- Coursera吴恩达机器学习课程 编程作业
- coursera机器学习第二周编程作业
- Coursera 多态编程作业思考
- Points
- points
- points
- 在maven项目移植时,Maven Dependencies不见了!!!
- 设计模式——Java动态代理
- C语言最简开发环境(续一)
- Scrolview 嵌套ListView 导致ListView条目不能展开的问题及原理详解
- 屏幕色温
- 【Coursera】编程题 Collinear Points
- java 文件读取
- 技术积累
- Redis使用详解之redhat系统上安装redis-3.2.8
- HDU 3047 Zjnu Stadium(带权并查集)
- leetcode解题之121 # Best Time to Buy and Sell Stock
- Matlab中几种括号的区别
- Simplify Path
- android四种启动lanuchMode