Collinear Points

普林斯顿算法课作业的python实现(三)Collinear Points Collinear Points问题思路代码结果 问题 这一次的编程作业是判断共线点。 问题大致描述如下: 给定平面上一些点,判断其中是否有四个及以上的点共线,把所有这些点找出来并连线。原题链接 思路 一种做法是暴力求解,遍历所有四个点,判断其是否共线。这种做法简单粗暴,但是时间复杂度在 O(N4)O(N^4)O(N4)。 另一种做法是以其中一个点为坐标原点,计算其他点到该点的倾角,按倾角的大小对其他点排序,找出三个以上连续相同的点,与该点本身,构成共线。遍历所有的点,重复上述操作,可得到所有共线组。 这 阅读详情

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 point
    private 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> {
        @Override
        public 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和max
                    if (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

algorithm第三周作业 Collinear Points cousera 上algorithm part I第三周课程讲述的是排序,包括插入排序、选择排序、希尔排序、归并排序和快速排序。其配套作业为Collinear Points,题目大意为给定若干点,求出其中的有四个及以上点共线的线段。 要求提交三个文件,Point.java,BruteCollinearPoints.java,FastCollinearPoints.java。 Point类 给定的的... 阅读详情

相关推荐

Coursera Algorithm Ⅰ week3 编程作业 Collinear Points

代码:https://github.com/RedemptionC/CourseraAlgorithms/tree/master/collinear 这是学完归并排序和快速排序之后的编程作业,需要提交3个类:BruteCollinearPoints.java,FastCollinearPoints.java和Point.java 在本文最后,会附上对课堂上教过的排序算法的总结 问题描述很简单:给出一系列的点,将其中包含四个点以上的最大线段找出来 这里的最大是指,如果一条线段包含五个点,那么就不要.

RedemptionC的博客 506

普林斯顿大学算法Week3:CollinearPoints共线模式识别(99分)--总结及代码

总结 (代码有详细注释) 本课讲了归并排序,作业应用是排序进行共线的模式识别,java1.8中的排序用的是tim排序,结合了归并排序与插入排序,属于稳定排序:排序之后相同元素的相对位置会不会改变 Point.java中有个非常重要的方法,compareTo(),它定义:纵坐标越小则点越小,如果纵坐标相同,那么横坐标越小则点越小.(如果作业中要求横坐标也是按顺序排列,那么排序后的点集映射到...

littlehaes的博客 1760

Assignment 3 | Collinear Points | Princeton Algorithms

得分: Correctness: 41/41 tests passed Memory: 1/1 tests passed Timing: 41/41 tests passed Aggregate score: 100.00% 问题要求: 给定平面中的n个不同点的集合,找到连接4个或更多点的子集的每个(最大)线段。 Points.java 需要实现的方法: public int compareTo(Point that) // compare two points by y-

qq_46497008的博客 448

普林斯顿大学算法 Week3:CollinearPoints 共线模式识别(95分)

FastCollinearPoints的实现中,个人认为最关键的一步是使用Merge Sort对以每个点为出发点的线段进行排序而不能用QuickSort,其原因在与排序的Stability稳定性。MergeSort不会打乱之前因为对Points排序后形成的有序线段组,才能保证后面循环检查线段斜率操作的有效性。 关于排序算法Stability的说明,见《算法(第四版)》第217页的2.5.1.8稳...

ichigoooo_wu的博客 725

普林斯顿算法课第三周作业

第三周作业模式识别 Programming Assignment 3: Pattern Recognition 题目地址:http://coursera.cs.princeton.edu/algs4/assignments/collinear.html ------------------------------------------ 这一周的问题是在一个给出N个随即点的平面

涂修竹的专栏 3767

points_colinear:此代码通过计算这些点的行列式来检查 3 个点是否共线-matlab开发

三个或更多点 P_1, P_2, P_3, ... 如果它们位于一条直线 L 上,则称它们共线。 点所在的直线,尤其是与几何图形(例如三角形)相关时,有时称为轴。 您可以在此链接中查看更多详细信息: http : //mathworld.wolfram.com/Collinear.html

Programming Assignment: Collinear Points

Programming Assignment: Collinear Points

仍歌杨柳春风 1603

3. ChaosBlade-Box平台安装

参考自:https://chaosblade.io/docs/about-chaosblade/box-introduce/通过ChaosBlade-Box可实现chaosblade等已托管工具自动化部署,按照社区的建立的混沌实验模型统一实验场景,根据主机、Kubernetes、应用来划分目标资源,通过目标管理器来控制,在实验创建页面,可以实现白屏化的目标资源选择。

lldhsds的专栏 2485

Princeton Algotithms Collinear Points

Princeton Algotithms Collinear Points 普林斯顿大学算法课第 3 次作业“共线点”。 虽然本次作业给出了暴力方法和快速方法,但是不要以为就能拿到很高的分数。 同样地,想要通过,非常简单,只要答案正确就行了,很容易通过。 但是想要拿到高分,还是不容易的。 以下代码获得 100 分,其中需要注意的点我罗列一下,具体可以看代码理解。 注意与 x 轴平行的点,斜率必须返...

凝神长老和他的朋友们 368

WhatsApp网页版扫码分析

扫码登录本质上是WhatsApp的多设备登录,设备之间可以独立运行,那么当我们首次通过WhatsApp扫码登录二维码时,到底发生了那些事情?交换了那些数据?

SocialMarketing的博客 5230

【教程4>第6章>第26节】基于FPGA的MMSE信道估计与均衡系统实现与整体测试,并对比LS信道估计

通过前面几个章节的学习,我们完成了MMSE信道估计和均衡系统。为了进一步验证MMSE信道估计的性能,我们在系统的最后,增加一个信道估计误差计算程序。由于MMSE信道估计,其主要优势在SNR较小时提现,因此测试对比时,我们在testbench中,将SNR设置为2db。然后m值,我们不考虑一个固定值,而是一直累加,直到所设置的仿真时间结束。通过对比可以看到,MMSE信道估计性能优于LS信道估计。这样方便FPGA中的误差计算。

FPGA/MATLAB学习教程/源码/项目合作开发 1598

Programming Assignment 3: Collinear Points

The problem. Given a set of N distinct points in the plane, draw every (maximal) line segment that connects a subset of 4 or more of the points. Point data type. Create an immutable data type Point...

weixin_30348519的博客 197

【异常】解决 Claude Code 及第三方插件提示 “API Error: 404“ 的配置修复指南

在使用 Claude 相关的 CLI 工具(如)或 IDE 插件进行开发辅助时,配置错误的模型参数是导致连接失败的常见原因。本文将针对这一典型报错进行复盘与解决。

奶爸的编程之路,也就一周冷个三天 7746

【Coursera】编程题 Collinear Points - Algorithms Part1, Week3

题目概述:http://coursera.cs.princeton.edu/algs4/assignments/collinear.html Point类和暴力算法(O(n^4))都很简单,就不写了。 写一个把复杂度降到n^2lg(n)的算法。 感觉写出来的东西很混乱。。 import java.util.ArrayList; import java.util.Arrays; i

OldDreamHYN的博客 1707

mongodb在游戏开发领域的优势

目前游戏服务器使用mysql作为数据库的较多,然而,使用mongodb来作为存储层,在某些方面比mysql更为方便和适合。

littleschemer的博客 1698

Arduino 系列:Arduino Due 系列 (基于 ATSAM3X8E)_(5).电源管理与电压调节

电源管理与电压调节是确保嵌入式系统稳定性和可靠性的关键环节。通过合理选择电源输入方式、使用高效的电压调节器、设计适当的滤波电路和实施动态电源管理,可以有效提高系统的性能和寿命。同时,使用电源调试工具和编写调试代码,可以帮助开发者及时发现和解决问题。希望本文档能为使用 Arduino Due 的开发者提供有用的信息和指导。

2401_87715305的博客 1308

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

题目正文: http://coursera.cs.princeton.edu/algs4/assignments/collinear.html 作业难点: 1、仔细思考会感觉有很多实现方法,但是如果没有适当使用排序,算法时间复杂度就会轻易超过要求。(包括暴力算法) 2、隐含需要实现自己的数据结构用来组织“线”的集合,当然也可以用Stack或者Queue或者LinkedList,但...

dianrangzhuo4225的博客 444

基于Simulink的六旋翼无人机动力分配仿真建模示例

六旋翼无人机概述特点:高冗余度、增强的负载能力和更好的故障容忍性。关键组件电机与螺旋桨:提供升力和推力。电调(ESC):控制电机转速。IMU(惯性测量单元):包括加速度计和陀螺仪,用于姿态估计。飞控板:处理传感器数据并生成控制信号。应用场景:航拍摄影、农业监测、物流配送等。仿真目标搭建一个简化的六旋翼无人机动力分配模型,涵盖电机驱动、姿态控制及位置控制过程。分析不同条件下的性能指标(如响应时间、稳定性等),并探讨六旋翼无人机的设计优化。

xiaoheshang_123的博客 484

普林斯顿大学算法课 编程作业3 共线点(Programming Assignment 3: Collinear Points)

n给定平面上n个不同的点,找到平面上所有有大于等于4个共线点的线段。

2301_76175651的博客 737

YOLO格式数据集【数据增强】终极脚本 | 70+种顶级数据增强方法 | 可带标签增强

YOLO格式数据集【数据增强】终极脚本 | 70+种顶级数据增强方法 | 可带标签增强

Coding... 5499

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

普林斯顿大学_算法公开课:Part_1_第一部分: Deques and Randomized Queues\Collinear Points\8 Puzzle\kd-Trees

本文主要介绍普林斯顿算法公开课的Part_1部分的核心算法,总体分两篇文章介绍。对于并查集相关内容请查看文章:https://blog.youkuaiyun.com/gzharryanonymous/article/details/80384195第二部分:Stacks and Queues对于这部分的内容比较简单,主要就是队列、栈的基本操作。代码如下:package stackQueue;import ed...

GZHarryAnonymous的博客 828

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

Algorithm I assignment Collinear

这本来应该是第三周的作业,但是由于其他作业逼近deadline,暂时推后了一周完成。 这周的assignment大大提高了我对这门课的看法,不得不说,Algorithms这门课的assignment部分设计得很好。为什么好?个人认为有以下几点: 程序要求解耦 循序渐进,这周的作业不允许使用hashcode() 输入变量不允许被程序改变 能做到1、3两点,在工程中也是高质量代码的体...

weixin_30312659的博客 179

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

LeetCode149 Max Points on a Line

题目: Givennpoints on a 2D plane, find the maximum number of points that lie on the same straight line. Example 1: Input: [[1,1],[2,2],[3,3]] Output: 3 Explana...

zhangjun62的博客 307

#LeetCode Max Points On A Line

public class Solution { public int maxPoints(Point[] points) { if (points.length == 0) return 0; if (points.length == 1) return 1; int maxP = 0;

hahazhouzhiqin的专栏 431

react-native-firebase Firestore Pipelines 架构设计:从 JS 序列化到原生执行的全链路解析

本篇技术指南基于 react-native-firebase 仓库中 Firestore Pipelines 模块的实现设计文档([okf-bundle/packages/firestore/pipelines.md](https://link.gitcode.com/i/4462c114257e527719fdfcc16cbf7fcf)),深入剖析 RNFB 如何将 JS 侧定义的 Pipeli

gitblog_01162的博客 994
上一篇: Interview Questions: Mergesort
下一篇: Interview Questions: Quicksort
绿色小光头
博客等级 码龄10年 10粉丝 301原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值