Collinear Points

Point.java

照要求补API即可。

import java.util.Comparator;
import edu.princeton.cs.algs4.StdDraw;public class Point implements Comparable<Point> {private final int x;     // x-coordinate of this pointprivate 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 (compareTo(that) == 0) {return Double.NEGATIVE_INFINITY;}if (this.x == that.x) {return Double.POSITIVE_INFINITY;}if (this.y == that.y) {return +0.0;}return 1.0 * (this.y - that.y) / (this.x - that.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.x < that.x) {return -1;} else if (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 SlopeComparator();}/*** 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 + ")";}private class SlopeComparator implements Comparator<Point> {@Overridepublic int compare(Point o1, Point o2) {if (slopeTo(o1) < slopeTo(o2)) {return -1;} else if (slopeTo(o1) > slopeTo(o2)) {return 1;} else {return 0;}}}/*** Unit tests the Point data type.*/public static void main(String[] args) {}
}

BruteCollinearPoints.java

暴力四重循环就完事了。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;public class BruteCollinearPoints {private final List<LineSegment> segments;public BruteCollinearPoints(Point[] points) {if (points == null) {throw new IllegalArgumentException();}Point[] copy = new Point[points.length];segments = new ArrayList<>();// 避免修改原数组,需要先复制下来for (int i = 0; i < points.length; i++) {if (points[i] == null) {throw new IllegalArgumentException();}copy[i] = points[i];}Arrays.sort(copy);for (int i = 0; i < copy.length - 1; i++) {if (copy[i].compareTo(copy[i + 1]) == 0) {throw new IllegalArgumentException();}}run(copy);}public int numberOfSegments() {return segments.size();}public LineSegment[] segments() {LineSegment[] res = new LineSegment[segments.size()];int i = 0;for (LineSegment segment : segments) {res[i++] = segment;}return res;}private void run(Point[] points) {int n = points.length;// 直接四重遍历for (int i = 0; i < n - 3; i++) {for (int j = i + 1; j < n - 2; j++) {double s1 = points[i].slopeTo(points[j]);for (int k = j + 1; k < n - 1; k++) {double s2 = points[i].slopeTo(points[k]);if (s1 == s2) {for (int m = k + 1; m < n; m++) {double s3 = points[i].slopeTo(points[m]);if (s1 == s3) {LineSegment temp = new LineSegment(points[i], points[m]);segments.add(temp);}}}}}}}
}

FastCollinearPoints.java

基本方法是以某一个点为基准,将其余点按照斜率大小进行排序,遍历得到的数组,相同斜率的点排在一起,即共线。问题在于如何找到线的端点以及排除重复端点对。思路如下:

  1. 一条线段的端点,与线段上其余点相比,其x/y值必然是最大/小的。所以可以直接用compareTo()来找到端点。
  2. 从基准点数组中,每次按顺序取一个基准点来排序斜率数组。在找到端点后,只保存以当前基准点为较小端点的线段,这样就可以避免端点对的重复。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;public class FastCollinearPoints {private final List<LineSegment> segments;public FastCollinearPoints(Point[] points) {if (points == null) {throw new IllegalArgumentException();}Point[] copy = new Point[points.length];segments = new ArrayList<>();for (int i = 0; i < points.length; i++) {if (points[i] == null) {throw new IllegalArgumentException();}copy[i] = points[i];}Arrays.sort(copy);for (int i = 0; i < copy.length - 1; i++) {if (copy[i].compareTo(copy[i + 1]) == 0) {throw new IllegalArgumentException();}}run(copy);}public int numberOfSegments() {return segments.size();}public LineSegment[] segments() {LineSegment[] res = new LineSegment[segments.size()];int i = 0;for (LineSegment segment : segments) {res[i++] = segment;}return res;}private void run(Point[] points) {int n = points.length;Point[] bases = Arrays.copyOf(points, n);   // 基准点数组int current = 0;while (current < n) {Point base = bases[current++];      // 选取下一个基准点Point min = base;       // 共线线段较小端点Point max = base;       // 贡献线段较大端点int count = 2;          // 线段中至少会有两个点Arrays.sort(points, base.slopeOrder());        // 按照与基准点的斜率进行排序for (int i = 0; i < n - 1; i++) {double s1 = base.slopeTo(points[i]);double s2 = base.slopeTo(points[i + 1]);if (s1 == s2) {count++;// 在新加入共线点的情况下更新小端点和大端点if (max.compareTo(points[i + 1]) < 0) {max = points[i + 1];} else if (min.compareTo(points[i + 1]) > 0) {min = points[i + 1];}// 当点i、i+1为最后两个点时,需要进行判断// 只保存以base为小端点的线段if (i == n - 2 && count >= 4 && base.compareTo(min) == 0) {LineSegment temp = new LineSegment(min, max);segments.add(temp);}} else {// 当相同斜率序列中断时,需要进行判断// 只保存以base为小端点的线段if (count >= 4 && base.compareTo(min) == 0) {LineSegment temp = new LineSegment(min, max);segments.add(temp);}// 开始新斜率序列时,需要将base与新斜率的第一个点进行比较,重置min和maxif (base.compareTo(points[i + 1]) > 0) {min = points[i + 1];max = base;} else {min = base;max = points[i + 1];}count = 2;}}}}
}

参考

SHICHENG - 【Algorithms, Part I】Week3 Collinear Points

Collinear Points相关推荐

  1. 普林斯顿算法课作业的python实现(三)Collinear Points

    Collinear Points 问题 思路 代码 结果 问题 这一次的编程作业是判断共线点. 问题大致描述如下: 给定平面上一些点,判断其中是否有四个及以上的点共线,把所有这些点找出来并连线.原题链 ...

  2. algorithm第三周作业 Collinear Points

    cousera 上algorithm part I第三周课程讲述的是排序,包括插入排序.选择排序.希尔排序.归并排序和快速排序.其配套作业为Collinear Points,题目大意为给定若干点,求出 ...

  3. Matlab最小面积包围四边形

    对于存在透视变换的物体,提取时最小面积包围矩形不能满足要求,google到一个求最小面积包围四边形的算法,虽然速度较慢.以提取书本为例,实验结果和代码如下. booktest.m I = imread ...

  4. 使用python和opencv构建集合求解器

    Have you ever played SET? SET is a game in which players race to identify patterns of three cards - ...

  5. Algorithm I assignment Collinear

    这本来应该是第三周的作业,但是由于其他作业逼近deadline,暂时推后了一周完成. 这周的assignment大大提高了我对这门课的看法,不得不说,Algorithms这门课的assignment部 ...

  6. ArcGIS制图之Sub Points点抽稀

    简介 Sub Points工具是 Esri 中国自主开发的一个插件,该工具优先考虑点在空间分布上的均匀合理性,并结合点数据中包含的 "优先级" 属性进行筛选.通过获取每个点在一定范 ...

  7. R语言可视化分面图、假设检验分组t检验、可视化单变量分组分面箱图(faceting bar plot)、添加误差条(error bar)、添加p值、添加抖动数据点(jitter points)

    R语言可视化分面图.假设检验分组t检验.可视化单变量分组分面箱图(faceting bar plot).添加误差条(error bar).添加p值.添加抖动数据点(jitter points) 目录

  8. seaborn使用violinplot函数可视化小提琴图、使用stripplot函数添加抖动数据点(jittered points)、显示数据的稠密程度

    seaborn使用violinplot函数可视化小提琴图.使用stripplot函数添加抖动数据点.显示数据的稠密程度(Seaborn violinplot with data points usin ...

  9. seaborn可视化水平箱图并添加抖动数据点(Horizontal boxplot with jittered points in Python)

    seaborn可视化水平箱图并添加抖动数据点(Horizontal boxplot with jittered points in Python) 目录 seaborn可视化水平箱图并添加抖动数据点( ...

最新文章

  1. 网传 10 年技术岗老员工身患绝症,1780 元被知名游戏公司裁掉?公司回应:已达成和解
  2. LinkedBlockingQueue 注记
  3. x VDC(x=3、5、6、8、12、24、48)继电器的引脚连接方式
  4. linux 基本指令-线上运维
  5. 20135206于佳心【家庭作业汇总】
  6. 有效的括号Python解法
  7. linux日志删除1天前,Linux自动删除n天前日志
  8. axios 上传文件 封装_axios使用及封装
  9. LeetCode 5367. 最长快乐前缀
  10. python获取当前路径和上一层路径_python获取当前路径和上一级路径
  11. 灭顶之灾之网络电视精灵——S2 2.8
  12. [老老实实学WCF] 第一篇 Hello WCF
  13. j计算机集成维护工具,USBOS v2.1电脑超级维护工具启动盘(集成最全winPE)
  14. “死扛”高并发大流量,大麦抢票的技术涅槃之路
  15. python re模块findall_python re模块findall()函数实例解析
  16. 虚拟机黑裙加载硬盘_在Promox VE(PVE)虚拟机安装黑群晖并开启硬盘休眠的方法...
  17. 格密码LLL算法:如何解决最短向量SVP问题(2)
  18. mysql员工表部门表_部门表 department 部门编号 dept_id 部门名称 汇总表
  19. x265探索与研究(一):x265下载安装与配置
  20. SQL语句创建、修改视图的方法

热门文章

  1. Python 清屏问题的解决
  2. 寻找基于SaaS研发总监
  3. 2022年起重机司机(限桥式起重机)考试练习题及在线模拟考试
  4. 一篇吃透Redis缓存穿透、雪崩、击穿问题
  5. 破云里步重华为什么说自己姓薛_破云主角也有弱点,小鱼栽在零食上,严峫被自己坑,步重华太好笑...
  6. SNAT,DNAT区别
  7. [C语言入门] 转义字符表
  8. css3 实现3D立方体的两种方法
  9. 公司来了个卷王,真让人奔溃
  10. c语言校验mac函数,C语言验证MAC地址字符串合法性函数