Collinear Points
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
基本方法是以某一个点为基准,将其余点按照斜率大小进行排序,遍历得到的数组,相同斜率的点排在一起,即共线。问题在于如何找到线的端点以及排除重复端点对。思路如下:
- 一条线段的端点,与线段上其余点相比,其x/y值必然是最大/小的。所以可以直接用compareTo()来找到端点。
- 从基准点数组中,每次按顺序取一个基准点来排序斜率数组。在找到端点后,只保存以当前基准点为较小端点的线段,这样就可以避免端点对的重复。
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相关推荐
- 普林斯顿算法课作业的python实现(三)Collinear Points
Collinear Points 问题 思路 代码 结果 问题 这一次的编程作业是判断共线点. 问题大致描述如下: 给定平面上一些点,判断其中是否有四个及以上的点共线,把所有这些点找出来并连线.原题链 ...
- algorithm第三周作业 Collinear Points
cousera 上algorithm part I第三周课程讲述的是排序,包括插入排序.选择排序.希尔排序.归并排序和快速排序.其配套作业为Collinear Points,题目大意为给定若干点,求出 ...
- Matlab最小面积包围四边形
对于存在透视变换的物体,提取时最小面积包围矩形不能满足要求,google到一个求最小面积包围四边形的算法,虽然速度较慢.以提取书本为例,实验结果和代码如下. booktest.m I = imread ...
- 使用python和opencv构建集合求解器
Have you ever played SET? SET is a game in which players race to identify patterns of three cards - ...
- Algorithm I assignment Collinear
这本来应该是第三周的作业,但是由于其他作业逼近deadline,暂时推后了一周完成. 这周的assignment大大提高了我对这门课的看法,不得不说,Algorithms这门课的assignment部 ...
- ArcGIS制图之Sub Points点抽稀
简介 Sub Points工具是 Esri 中国自主开发的一个插件,该工具优先考虑点在空间分布上的均匀合理性,并结合点数据中包含的 "优先级" 属性进行筛选.通过获取每个点在一定范 ...
- R语言可视化分面图、假设检验分组t检验、可视化单变量分组分面箱图(faceting bar plot)、添加误差条(error bar)、添加p值、添加抖动数据点(jitter points)
R语言可视化分面图.假设检验分组t检验.可视化单变量分组分面箱图(faceting bar plot).添加误差条(error bar).添加p值.添加抖动数据点(jitter points) 目录
- seaborn使用violinplot函数可视化小提琴图、使用stripplot函数添加抖动数据点(jittered points)、显示数据的稠密程度
seaborn使用violinplot函数可视化小提琴图.使用stripplot函数添加抖动数据点.显示数据的稠密程度(Seaborn violinplot with data points usin ...
- seaborn可视化水平箱图并添加抖动数据点(Horizontal boxplot with jittered points in Python)
seaborn可视化水平箱图并添加抖动数据点(Horizontal boxplot with jittered points in Python) 目录 seaborn可视化水平箱图并添加抖动数据点( ...
最新文章
- 网传 10 年技术岗老员工身患绝症,1780 元被知名游戏公司裁掉?公司回应:已达成和解
- LinkedBlockingQueue 注记
- x VDC(x=3、5、6、8、12、24、48)继电器的引脚连接方式
- linux 基本指令-线上运维
- 20135206于佳心【家庭作业汇总】
- 有效的括号Python解法
- linux日志删除1天前,Linux自动删除n天前日志
- axios 上传文件 封装_axios使用及封装
- LeetCode 5367. 最长快乐前缀
- python获取当前路径和上一层路径_python获取当前路径和上一级路径
- 灭顶之灾之网络电视精灵——S2 2.8
- [老老实实学WCF] 第一篇 Hello WCF
- j计算机集成维护工具,USBOS v2.1电脑超级维护工具启动盘(集成最全winPE)
- “死扛”高并发大流量,大麦抢票的技术涅槃之路
- python re模块findall_python re模块findall()函数实例解析
- 虚拟机黑裙加载硬盘_在Promox VE(PVE)虚拟机安装黑群晖并开启硬盘休眠的方法...
- 格密码LLL算法:如何解决最短向量SVP问题(2)
- mysql员工表部门表_部门表 department 部门编号 dept_id 部门名称 汇总表
- x265探索与研究(一):x265下载安装与配置
- SQL语句创建、修改视图的方法