算法导论第四版学习——习题三Collinear Points

题目正文:

http://coursera.cs.princeton.edu/algs4/assignments/collinear.html

作业难点:

1、仔细思考会感觉有很多实现方法,但是如果没有适当使用排序,算法时间复杂度就会轻易超过要求。(包括暴力算法)

2、隐含需要实现自己的数据结构用来组织“线”的集合,当然也可以用Stack或者Queue或者LinkedList,但是我个人是自己实现的。

3、由于一条线段只能出现一次,所以有一个去重的问题。(最难)

作业技巧:

1、基本按照题目的先后顺序实现,结合视频学习中的一些知识点就可以把任务串起来,不会无从下手。

2、SlopTo的计算结果和点数组的排列顺序有关吗?A.SlopeTo(B)和B.SlopeTo(A)其实是一样的,合理利用cache防止多次计算。

3、在暴力方法中,引入排序可以解决去重问题。

4、如果去重是通过在结果集合中查找是否存在,就铁定会超过复杂度要求,所以必须在添加结果集之前就能判断。

这里就有一个重要推论:a-b-c-d线段,无论从a开始查找还是从b开始查找,线段最大和最小点都不变为a和d,所以我们只需要找到起始点为线段最小点的线段就可以了,其他线段均抛弃即可

代码参考:

(这是我自己亲测100分的答案,不代表写得最好,请在自己实在完成不了的时候再看,不然的话做这个题目的意义一点都没有)

  1 import edu.princeton.cs.algs4.StdDraw;
  2
  3 /******************************************************************************
  4  *  Compilation:  javac Point.java
  5  *  Execution:    java Point
  6  *  Dependencies: none
  7  *
  8  *  An immutable data type for points in the plane.
  9  *  For use on Coursera, Algorithms Part I programming assignment.
 10  *
 11  ******************************************************************************/
 12 import java.util.Comparator;
 13
 14
 15 public class Point implements Comparable<Point> {
 16     private final int x; // x-coordinate of this point
 17     private final int y; // y-coordinate of this point
 18
 19     /**
 20      * Initializes a new point.
 21      *
 22      * @param  x the <em>x</em>-coordinate of the point
 23      * @param  y the <em>y</em>-coordinate of the point
 24      */
 25     public Point(int x, int y) {
 26         /* DO NOT MODIFY */
 27         this.x = x;
 28         this.y = y;
 29     }
 30
 31     /**
 32      * Draws this point to standard draw.
 33      */
 34     public void draw() {
 35         /* DO NOT MODIFY */
 36         StdDraw.point(x, y);
 37     }
 38
 39     /**
 40      * Draws the line segment between this point and the specified point
 41      * to standard draw.
 42      *
 43      * @param that the other point
 44      */
 45     public void drawTo(Point that) {
 46         /* DO NOT MODIFY */
 47         StdDraw.line(this.x, this.y, that.x, that.y);
 48     }
 49
 50     /**
 51      * Returns the slope between this point and the specified point.
 52      * Formally, if the two points are (x0, y0) and (x1, y1), then the slope
 53      * is (y1 - y0) / (x1 - x0). For completeness, the slope is defined to be
 54      * +0.0 if the line segment connecting the two points is horizontal;
 55      * Double.POSITIVE_INFINITY if the line segment is vertical;
 56      * and Double.NEGATIVE_INFINITY if (x0, y0) and (x1, y1) are equal.
 57      *
 58      * @param  that the other point
 59      * @return the slope between this point and the specified point
 60      */
 61     public double slopeTo(Point that) {
 62         if ((this.x == that.x) && (this.y == that.y)) {
 63             return Double.NEGATIVE_INFINITY;
 64         } else if (this.x == that.x) {
 65             return Double.POSITIVE_INFINITY;
 66         } else if (this.y == that.y) {
 67             return 0;
 68         } else {
 69             return (that.y - this.y) / (double) (that.x - this.x);
 70         }
 71     }
 72
 73     /**
 74      * Compares two points by y-coordinate, breaking ties by x-coordinate.
 75      * Formally, the invoking point (x0, y0) is less than the argument point
 76      * (x1, y1) if and only if either y0 < y1 or if y0 = y1 and x0 < x1.
 77      *
 78      * @param  that the other point
 79      * @return the value <tt>0</tt> if this point is equal to the argument
 80      *         point (x0 = x1 and y0 = y1);
 81      *         a negative integer if this point is less than the argument
 82      *         point; and a positive integer if this point is greater than the
 83      *         argument point
 84      */
 85     public int compareTo(Point that) {
 86         if ((this.x == that.x) && (this.y == that.y)) {
 87             return 0;
 88         } else if ((that.y > this.y) ||
 89                 ((that.y == this.y) && (that.x > this.x))) {
 90             return -1;
 91         } else {
 92             return 1;
 93         }
 94     }
 95
 96     /**
 97      * Compares two points by the slope they make with this point.
 98      * The slope is defined as in the slopeTo() method.
 99      *
100      * @return the Comparator that defines this ordering on points
101      */
102     public Comparator<Point> slopeOrder() {
103         return new SlopeOrder(this);
104     }
105
106     /**
107      * Returns a string representation of this point.
108      * This method is provide for debugging;
109      * your program should not rely on the format of the string representation.
110      *
111      * @return a string representation of this point
112      */
113     public String toString() {
114         /* DO NOT MODIFY */
115         return "(" + x + ", " + y + ")";
116     }
117
118     /**
119      * Unit tests the Point data type.
120      */
121     public static void main(String[] args) {
122         /* YOUR CODE HERE */
123     }
124
125     private class SlopeOrder implements Comparator<Point> {
126         private Point p0;
127
128         public SlopeOrder(Point invokePoint) {
129             p0 = invokePoint;
130         }
131
132         public int compare(Point p1, Point p2) {
133             double d01 = p0.slopeTo(p1);
134             double d02 = p0.slopeTo(p2);
135
136             if (d01 < d02) {
137                 return -1;
138             } else if (d01 > d02) {
139                 return 1;
140             } else {
141                 return 0;
142             }
143         }
144     }
145 }

Point

  1 import edu.princeton.cs.algs4.In;
  2 import edu.princeton.cs.algs4.StdDraw;
  3 import edu.princeton.cs.algs4.StdOut;
  4 import java.util.Arrays;
  5
  6 public class BruteCollinearPoints {
  7     private int lineNumber;
  8     private Node last;
  9
 10     public BruteCollinearPoints(Point[] points) // finds all line segments containing 4 points
 11      {
 12
 13         if (points == null) {
 14             throw new NullPointerException();
 15         }
 16
 17         lineNumber = 0;
 18
 19         int num = points.length;
 20
 21         Point[] clone = new Point[num];
 22
 23         for (int i = 0; i < num; i++) {
 24             if (points[i] == null) {
 25                 throw new NullPointerException();
 26             }
 27
 28             for (int j = i + 1; j < num; j++) {
 29                 if (points[i].compareTo(points[j]) == 0) {
 30                     throw new IllegalArgumentException();
 31                 }
 32             }
 33             clone[i] = points[i];
 34         }
 35         Arrays.sort(clone);
 36         for (int i = 0; i < num; i++) {
 37             for (int j = i+1; j < num; j++) {
 38                 for (int m = j+1; m < num; m++) {
 39                     for (int n = m+1; n < num; n++) {
 40                         double d01 = clone[i].slopeTo(clone[j]);
 41                         double d02 = clone[j].slopeTo(clone[m]);
 42                         double d03 = clone[m].slopeTo(clone[n]);
 43
 44                         if (d01 == d02 && d02 == d03)  {
 45                             if (last != null) {
 46                                 Node newNode = new Node();
 47                                 newNode.prev = last;
 48                                 newNode.value = new LineSegment(clone[i],
 49                                         clone[n]);
 50                                 last = newNode;
 51                             } else {
 52                                 last = new Node();
 53                                 last.value = new LineSegment(clone[i],
 54                                         clone[n]);
 55                             }
 56
 57                             lineNumber++;
 58                         }
 59                     }
 60                 }
 61             }
 62         }
 63     }
 64
 65     public int numberOfSegments() // the number of line segments
 66      {
 67         return lineNumber;
 68     }
 69
 70     public LineSegment[] segments() // the line segments
 71      {
 72         LineSegment[] lines = new LineSegment[lineNumber];
 73         Node current = last;
 74
 75         for (int i = 0; i < lineNumber; i++) {
 76             lines[i] = current.value;
 77             current = current.prev;
 78         }
 79
 80         return lines;
 81     }
 82
 83     public static void main(String[] args) {
 84         // read the n points from a file
 85         In in = new In(args[0]);
 86         int n = in.readInt();
 87         Point[] points = new Point[n];
 88
 89         for (int i = 0; i < n; i++) {
 90             int x = in.readInt();
 91             int y = in.readInt();
 92             points[i] = new Point(x, y);
 93         }
 94
 95         // draw the points
 96         StdDraw.enableDoubleBuffering();
 97         StdDraw.setXscale(0, 32768);
 98         StdDraw.setYscale(0, 32768);
 99
100         for (Point p : points) {
101             p.draw();
102         }
103
104         StdDraw.show();
105
106         // print and draw the line segments
107         BruteCollinearPoints collinear = new BruteCollinearPoints(points);
108
109         for (LineSegment segment : collinear.segments()) {
110             StdOut.println(segment);
111             segment.draw();
112         }
113
114         StdDraw.show();
115     }
116
117     private class Node {
118         private LineSegment value;
119         private Node prev;
120     }
121 }

BruteCollinearPoints

  1 import edu.princeton.cs.algs4.In;
  2 import edu.princeton.cs.algs4.StdDraw;
  3 import edu.princeton.cs.algs4.StdOut;
  4
  5 import java.util.Arrays;
  6
  7 public class FastCollinearPoints {
  8     private int lineNumber;
  9     private Node last;
 10
 11     public FastCollinearPoints(Point[] points) // finds all line segments containing 4 or more points
 12      {
 13         if (points == null) {
 14             throw new NullPointerException();
 15         }
 16
 17         lineNumber = 0;
 18
 19         int num = points.length;
 20         Point[] clone = new Point[num];
 21
 22         for (int i = 0; i < num; i++) {
 23             if (points[i] == null) {
 24                 throw new NullPointerException();
 25             }
 26
 27             for (int j = i + 1; j < num; j++) {
 28                 if (points[i].compareTo(points[j]) == 0) {
 29                     throw new IllegalArgumentException();
 30                 }
 31             }
 32             clone[i] = points[i];
 33         }
 34         Arrays.sort(clone);
 35
 36         if (num < 4) {
 37             return;
 38         }
 39
 40         for (int i = 0; i < num - 1; i++) {
 41             int tempPointsNum = 0;
 42             Point[] tempPoints = new Point[num - 1];
 43
 44             for (int j = 0; j < num; j++) {
 45                 if (i != j) tempPoints[tempPointsNum++] = clone[j];
 46             }
 47
 48             Arrays.sort(tempPoints, clone[i].slopeOrder());
 49
 50             int count = 0;
 51             Point min = null;
 52             Point max = null;
 53
 54             for (int j = 0; j < (tempPointsNum - 1); j++) {
 55                 if (clone[i].slopeTo(tempPoints[j]) == clone[i].slopeTo(
 56                             tempPoints[j + 1])) {
 57                     if (min == null) {
 58                         if (clone[i].compareTo(tempPoints[j]) > 0) {
 59                             max = clone[i];
 60                             min = tempPoints[j];
 61                         } else {
 62                             max = tempPoints[j];
 63                             min = clone[i];
 64                         }
 65                     }
 66
 67                     if (min.compareTo(tempPoints[j + 1]) > 0) {
 68                         min = tempPoints[j + 1];
 69                     }
 70
 71                     if (max.compareTo(tempPoints[j + 1]) < 0) {
 72                         max = tempPoints[j + 1];
 73                     }
 74
 75                     count++;
 76
 77                     if (j == (tempPointsNum - 2)) {
 78                         if (count >= 2 && clone[i].compareTo(min) == 0) {
 79                             addLine(min, max);
 80                         }
 81
 82                         count = 0;
 83                         min = null;
 84                         max = null;
 85                     }
 86                 } else {
 87                     if (count >= 2 && clone[i].compareTo(min) == 0) {
 88                         addLine(min, max);
 89                     }
 90
 91                     count = 0;
 92                     min = null;
 93                     max = null;
 94                 }
 95             }
 96         }
 97     }
 98
 99     private void addLine(Point a, Point b) {
100         if (last != null) {
101             Node newNode = new Node();
102             newNode.prev = last;
103             newNode.value = new LineSegment(a, b);
104             last = newNode;
105         } else {
106             last = new Node();
107             last.value = new LineSegment(a, b);
108         }
109         lineNumber++;
110     }
111
112     public int numberOfSegments() // the number of line segments
113      {
114         return lineNumber;
115     }
116
117     public LineSegment[] segments() // the line segments
118      {
119         LineSegment[] lines = new LineSegment[lineNumber];
120         Node current = last;
121
122         for (int i = 0; i < lineNumber; i++) {
123             lines[i] = current.value;
124             current = current.prev;
125         }
126
127         return lines;
128     }
129
130     public static void main(String[] args) {
131         // read the n points from a file
132         In in = new In(args[0]);
133         int n = in.readInt();
134         Point[] points = new Point[n];
135
136         for (int i = 0; i < n; i++) {
137             int x = in.readInt();
138             int y = in.readInt();
139             points[i] = new Point(x, y);
140         }
141
142         // draw the points
143         StdDraw.enableDoubleBuffering();
144         StdDraw.setXscale(0, 32768);
145         StdDraw.setYscale(0, 32768);
146
147         for (Point p : points) {
148             p.draw();
149         }
150
151         StdDraw.show();
152
153         // print and draw the line segments
154         FastCollinearPoints collinear = new FastCollinearPoints(points);
155
156         for (LineSegment segment : collinear.segments()) {
157             StdOut.println(segment);
158             segment.draw();
159         }
160
161         StdDraw.show();
162     }
163
164     private class Node {
165         private LineSegment value;
166         private Node prev;
167     }
168 }

FastCollinearPoints

时间: 2024-11-10 01:11:09

算法导论第四版学习——习题三Collinear Points的相关文章

算法导论第四版学习——习题一Percolation

题目正文: http://coursera.cs.princeton.edu/algs4/assignments/percolation.html 作业难点: 1.backwash(倒灌)的判断,如果不使用另一个WeightedUnionFind对象,要在要求的时间和空间范围内实现是很困难的 和论坛里的学生一样,尝试只只使用上部的虚拟节点,下部判断联通使用循环+break,提交后不满足时间复杂度要求 你也可以不考虑backwash这种情况,因为backwash对连通性并没有直接影响 2.Unio

算法导论第四版学习——习题五Kd-Tree

题目正文: http://coursera.cs.princeton.edu/algs4/assignments/kdtree.html 作业难点: 如何组织自己的数据结构是本道题的最难点,基本上有思路就肯定可以完成.题目一定要看仔细,基本上2dtree部分已经把实现原理说清楚了. 作业技巧: 1.逐步实现,实现完成后用insert.contain测试下,没问题再写draw,测试没问题再写其余的. 2.重复输入的问题不要忘了 3.range虽然api里写的是all point inside th

算法导论第四版学习——习题二Deques and Randomized Queues

题目正文: http://coursera.cs.princeton.edu/algs4/assignments/queues.html 作业难点: 1.选择使用链表还是数组,将会是第一个问题,选择合适会减少很多工作量. 2.并行从RandomizedQueue中取两个枚举,这两个枚举必须是不一样的,所以有很多偷懒的“伪随机”是行不通的. 3.SubSet仅需K存储而不是N存储,即可实现.(这个我也没想到方法实现) 作业技巧: 1.可遍数组和邻接节点两种数据结构都已经给你了,你只要改改,基本上实

算法导论第四版学习——习题四8 Puzzle

题目正文: http://coursera.cs.princeton.edu/algs4/assignments/8puzzle.html 作业难点: 1.如何验证Puzzle是否可解?题目中有提示,如果相邻两个格子交换后得到的“Twin Puzzle”进行求解,如果Twin有解那么原始Puzzle就无解. 作业技巧: 1.checklist提到把Twin Puzzle和Puzzle放在一个Priority Queue中,其实就是在设计自己的Node数据结构的时候加一个boolean类型标识是否

算法第四版学习笔记之快速排序 QuickSort

软件:DrJava 参考书:算法(第四版) 章节:2.3快速排序(以下截图是算法配套视频所讲内容截图) 1:快速排序 2:

ubuntu命令行下java工程编辑与算法(第四版)环境配置

ubuntu命令行下java工程编辑与算法(第四版)环境配置 java 命令行 javac java 在学习算法(第四版)中的实例时,因需要安装配套的java编译环境,可是在编译java文件的时候总是出各种错误,特在此总结一下. ubuntu下java环境配置 由于网上教程比较多,而且也较全面,特此摆放一个链接,跟着此教程总就可以配置好oracle的java jdk,如果想更加省事,直接在命令行下键入java,会提示安装各种开源java jdk,只需要一个命令即可: sudo apt-get i

马克思主义基本原理概论》学生辅学读本(第四版)习题答案

马克思主义基本原理概论 学生辅学读本(第四版)习题答案 逄锦聚<马克思主义基本原理概论>学生辅学读本(第四版)习题答案?本书是马克思主义理论研究和建设工程重点教材<马克思主义基本原理概论>(2013年修订版)的配套用书,根据党的十八大精神,进行了相应内容的修改.本书依据教材的逻辑体系,从适合学生学习的角度出发进行内容设计,每章包括"明确学习目标"."教师导航分析"."观点案例点评"."游弋大千题海".&

计算机组成原理_第四版课后习题答案(完整版)

计算机组成原理_第四版课后习题答案(完整版) ?第一章 1.?比较数字计算机和模拟计算机的特点. 解:模拟计算机的特点:数值由连续量来表示,运算过程是连续的: 数字计算机的特点:数值由数字量(离散量)来表示,运算按位进行. 两者主要区别见P1?表1.1. 2.?数字计算机如何分类?分类的依据是什么? 解:分类: 数字计算机分为专用计算机和通用计算机.通用计算机又分为巨型机.大型机. 中型机.小型机.微型机和单片机六类. 分类依据:专用和通用是根据计算机的效率.速度.价格.运行的经济性和适应性来划

算法(第四版)C#题解&mdash;&mdash;1.3.49 用 6 个栈实现一个 O(1) 队列

因为这个解法有点复杂,因此单独开一贴介绍. <算法(第四版)>中的题目是这样的: 1.3.49 栈与队列.用有限个栈实现一个队列,保证每个队列操作(在最坏情况下)都只需要常数次的栈操作. 那么这里就使用六个栈来解决这个问题. 这个算法来自于这篇论文. 原文里用的是 Pure Lisp,不过语法很简单,还是很容易看懂的. 先导知识--用两个栈模拟一个队列 如何使用两个栈来模拟一个队列操作? 这是一道很经典的题目,答案也有很多种,这里只介绍之后会用到的一种方法. 首先我们有两个栈,H 和 T,分别