Coursera普林斯顿算法课第三次作业

2023-11-11 17:38

本文主要是介绍Coursera普林斯顿算法课第三次作业,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Point: 重点是Comparable和Comparator接口的区别和实现。另外需要特别注意点的坐标是整数类型而斜率是浮点数,所以在计算斜率时可以乘以1.0。其次要注意Java中正负零不相等的问题,即0/5与0/(-5)不相同。

import java.util.Comparator;
import edu.princeton.cs.algs4.StdDraw;public class Point implements Comparable<Point>{private int x;private int y;public Point(int x, int y){this.x = x;this.y = y;}// x and y are between 0 and 32767public void draw(){StdDraw.point(x, y);}// StdDraw with input between 0 and 1public void drawTo(Point that){StdDraw.line(x, y, that.x, that.y);}public String toString() {return "Point [x=" + x + ", y=" + y + "]";}// implementation for Comparablepublic int compareTo(Point that) {if(y < that.y || (y == that.y && x < that.x)){return -1;}else if(y == that.y && x == that.x){return 0;}else{return 1;}	}public double slopeTo(Point that){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; // negative zero != positive zero}else{return (that.y - y) * 1.0 /(that.x - x); // integer to double}}public Comparator<Point> slopeOrder(){return new BySlope();}// implementation for Comparatorprivate class BySlope implements Comparator<Point>{public int compare(Point o1, Point o2) {if(slopeTo(o1) < slopeTo(o2)) return -1;if(slopeTo(o1) > slopeTo(o2)) return 1;return 0;}	}}

LineSegment:不做要求,测试时会提供。注意StdDraw的使用。

import edu.princeton.cs.algs4.StdDraw;public class LineSegment {private Point p_top;private Point p_bot;public LineSegment(Point p, Point q){p_top = p;p_bot = q;}public void draw(){p_top.drawTo(p_bot);}public String toString() {return "LineSegment [p1=" + p_top + ", p2=" + p_bot + "]";}public static void main(String[] args){Point p1 = new Point(15000,18000);Point p2 = new Point(8000,22000);Point p3 = new Point(600,9000);Point p4 = new Point(9000,5000);Point p5 = new Point(12000,10000);StdDraw.enableDoubleBuffering();StdDraw.setXscale(0, 32768);StdDraw.setYscale(0, 32768);StdDraw.setPenRadius(0.01);StdDraw.setPenColor(StdDraw.BLUE);p1.draw();p2.draw();p3.draw();p4.draw();p5.draw();StdDraw.show();StdDraw.setPenColor(StdDraw.MAGENTA);p1.drawTo(p5);p2.drawTo(p4);StdDraw.setPenColor(StdDraw.RED);p3.drawTo(p2);StdDraw.show();}
}

BruteCollinearPoints:使用了ArrayList及其自带的toArray方法。时间复杂度控制在N^4以内。注意不能直接对构造方法输入参数points进行排序,需要进行深度复制。

import java.util.ArrayList;
import edu.princeton.cs.algs4.Merge;public class BruteCollinearPoints {private Point[] pts;private ArrayList<LineSegment> lines;public BruteCollinearPoints(Point[] points){// deep copy to avoid mutating the constructor argumentcheckNullArgument(points);this.pts = new Point[points.length]; for(int k = 0; k < points.length; k++){pts[k] = points[k];}checkDuplicatedElement(pts); // mergesortlines = new ArrayList<LineSegment>(); // to avoid NullPointerExceptionfor(int k1 = 0; k1 < pts.length; k1++){for(int k2 = k1 + 1; k2 < pts.length; k2++){for(int k3 = k2 + 1; k3 < pts.length; k3++){if(pts[k1].slopeTo(pts[k2]) == pts[k1].slopeTo(pts[k3])){for(int k4 = k3 + 1; k4 < pts.length; k4++){if(pts[k1].slopeTo(pts[k2]) == pts[k1].slopeTo(pts[k4])){// k1, k2, k3, k4 are already sortedlines.add(new LineSegment(pts[k1], pts[k4]));}}}}}}}public int numberOfSegments(){return lines.size();}// line segment will contain at most 4 collinear pointspublic LineSegment[] segments(){return lines.toArray(new LineSegment[numberOfSegments()]);}private void checkDuplicatedElement(Point[] points){// sort input array by natural orderMerge.sort(points);// duplicated elementfor(int i=1; i<points.length; i++){if(points[i].slopeTo(points[i-1]) == Double.NEGATIVE_INFINITY){throw new IllegalArgumentException("Input contains repeated element!\n");}}}private void checkNullArgument(Point[] points){// null arrayif(points == null){throw new IllegalArgumentException("Input cannot be null!\n");}// null elementfor(int i = 0; i < points.length; i++){if(points[i] == null){throw new IllegalArgumentException("Input contains null element!\n");}	}}}

FastCollinearPoints:难点在于如何确认找到的segment是不是之前找到过的线段的subsegment,同时要保证时间复杂度在N*N*lg(N)以内。以下代码通过使用复杂度为lg(N)的BinarySearch成功地完成了任务。

import java.util.ArrayList;
import java.util.Arrays;import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.Merge;
import edu.princeton.cs.algs4.StdDraw;
import edu.princeton.cs.algs4.StdOut;public class FastCollinearPoints {private Point[] pts;private ArrayList<LineSegment> lines;/*** constructor ~ n*nlg(n)* @param points*/public FastCollinearPoints(Point[] points){checkNullArgument(points);this.pts = new Point[points.length]; for(int k = 0; k < points.length; k++){pts[k] = points[k];}checkDuplicatedElement(pts); // mergesort ~ nlg(n)lines = new ArrayList<LineSegment>(); // to avoid NullPointerException// IndexOutOfBoundsException for i < pts.lengthfor(int i = 0; i < pts.length - 1; i++){Double[] slopesB4 = new Double[i]; // slopes with points upstreamPoint[] pointsAf = new Point[pts.length - i - 1]; // points downstreamfor(int k = 0; k < i; k++) {slopesB4[k] = pts[i].slopeTo(pts[k]);}for(int j = 0; j < pts.length - i - 1; j++) { pointsAf[j] = pts[j + i + 1]; }// sort upstream slopes by natural order ~ nlg(n)Merge.sort(slopesB4); // sort downstream points by slope order to pts[i] ~ nlg(n)Arrays.sort(pointsAf, pts[i].slopeOrder()); addSegment(slopesB4, pts[i], pointsAf); // ~ nlg(n)}}/*** add appropriate line segment ~ nlg(n)* @param slopesB4: slopes of upstream points to point p* @param p: the origin point* @param pointsAf: downstream points*/private void addSegment(Double[] slopesB4, Point p, Point[] pointsAf){int count = 1;double lastSlope = p.slopeTo(pointsAf[0]);for(int i = 1; i < pointsAf.length; i++){double slope = p.slopeTo(pointsAf[i]);if(slope != lastSlope){if(count >= 3 && !subSegment(lastSlope, slopesB4)){lines.add(new LineSegment(p, pointsAf[i - 1]));}		count = 1;}else{count++; // the loop terminates with the last possible segment unchecked}lastSlope = slope;}// check the last pointif(count >= 3 && !subSegment(lastSlope, slopesB4)){lines.add(new LineSegment(p, pointsAf[pointsAf.length - 1]));}}/*** binary search the given slope in slopsB4 ~ lg(n)* @param s: the given slope* @param slopes: of upstream points to the origin point* @return */private boolean subSegment(double s, Double[] slopes){int lo = 0;int hi = slopes.length - 1;while(lo <= hi){int mid = lo + (hi - lo) / 2;if(s < slopes[mid]) hi = mid - 1;else if(s > slopes[mid]) lo = mid + 1;	else return true;}return false;}public int numberOfSegments(){return lines.size();}public LineSegment[] segments(){return lines.toArray(new LineSegment[numberOfSegments()]);}private void checkDuplicatedElement(Point[] points){// sort input array by natural orderMerge.sort(points);// duplicated elementfor(int i=1; i<points.length; i++){if(points[i].slopeTo(points[i-1]) == Double.NEGATIVE_INFINITY){throw new IllegalArgumentException("Input contains repeated element!\n");}}}private void checkNullArgument(Point[] points){// null arrayif(points == null){throw new IllegalArgumentException("Input cannot be null!\n");}// null elementfor(int i = 0; i < points.length; i++){if(points[i] == null){throw new IllegalArgumentException("Input contains null element!\n");}	}}public static void main(String[] args){// read n points from a fileIn in = new In(args[0]);int n = in.readInt();Point[] points = new Point[n];for(int i = 0; i < n; i++){int x = in.readInt();int y = in.readInt();points[i] = new Point(x, y);}// draw pointsStdDraw.enableDoubleBuffering();StdDraw.setXscale(0, 32768);StdDraw.setYscale(0, 32768);for(Point p : points){p.draw();}StdDraw.show();FastCollinearPoints collinear = new FastCollinearPoints(points);for(LineSegment sg : collinear.segments()){StdOut.println(sg);sg.draw();}StdDraw.show();}}

这篇关于Coursera普林斯顿算法课第三次作业的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/391745

相关文章

openCV中KNN算法的实现

《openCV中KNN算法的实现》KNN算法是一种简单且常用的分类算法,本文主要介绍了openCV中KNN算法的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录KNN算法流程使用OpenCV实现KNNOpenCV 是一个开源的跨平台计算机视觉库,它提供了各

springboot+dubbo实现时间轮算法

《springboot+dubbo实现时间轮算法》时间轮是一种高效利用线程资源进行批量化调度的算法,本文主要介绍了springboot+dubbo实现时间轮算法,文中通过示例代码介绍的非常详细,对大家... 目录前言一、参数说明二、具体实现1、HashedwheelTimer2、createWheel3、n

SpringBoot实现MD5加盐算法的示例代码

《SpringBoot实现MD5加盐算法的示例代码》加盐算法是一种用于增强密码安全性的技术,本文主要介绍了SpringBoot实现MD5加盐算法的示例代码,文中通过示例代码介绍的非常详细,对大家的学习... 目录一、什么是加盐算法二、如何实现加盐算法2.1 加盐算法代码实现2.2 注册页面中进行密码加盐2.

Java时间轮调度算法的代码实现

《Java时间轮调度算法的代码实现》时间轮是一种高效的定时调度算法,主要用于管理延时任务或周期性任务,它通过一个环形数组(时间轮)和指针来实现,将大量定时任务分摊到固定的时间槽中,极大地降低了时间复杂... 目录1、简述2、时间轮的原理3. 时间轮的实现步骤3.1 定义时间槽3.2 定义时间轮3.3 使用时

如何通过Golang的container/list实现LRU缓存算法

《如何通过Golang的container/list实现LRU缓存算法》文章介绍了Go语言中container/list包实现的双向链表,并探讨了如何使用链表实现LRU缓存,LRU缓存通过维护一个双向... 目录力扣:146. LRU 缓存主要结构 List 和 Element常用方法1. 初始化链表2.

golang字符串匹配算法解读

《golang字符串匹配算法解读》文章介绍了字符串匹配算法的原理,特别是Knuth-Morris-Pratt(KMP)算法,该算法通过构建模式串的前缀表来减少匹配时的不必要的字符比较,从而提高效率,在... 目录简介KMP实现代码总结简介字符串匹配算法主要用于在一个较长的文本串中查找一个较短的字符串(称为

通俗易懂的Java常见限流算法具体实现

《通俗易懂的Java常见限流算法具体实现》:本文主要介绍Java常见限流算法具体实现的相关资料,包括漏桶算法、令牌桶算法、Nginx限流和Redis+Lua限流的实现原理和具体步骤,并比较了它们的... 目录一、漏桶算法1.漏桶算法的思想和原理2.具体实现二、令牌桶算法1.令牌桶算法流程:2.具体实现2.1

Python中的随机森林算法与实战

《Python中的随机森林算法与实战》本文详细介绍了随机森林算法,包括其原理、实现步骤、分类和回归案例,并讨论了其优点和缺点,通过面向对象编程实现了一个简单的随机森林模型,并应用于鸢尾花分类和波士顿房... 目录1、随机森林算法概述2、随机森林的原理3、实现步骤4、分类案例:使用随机森林预测鸢尾花品种4.1

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

作业提交过程之HDFSMapReduce

作业提交全过程详解 (1)作业提交 第1步:Client调用job.waitForCompletion方法,向整个集群提交MapReduce作业。 第2步:Client向RM申请一个作业id。 第3步:RM给Client返回该job资源的提交路径和作业id。 第4步:Client提交jar包、切片信息和配置文件到指定的资源提交路径。 第5步:Client提交完资源后,向RM申请运行MrAp