2020-01-09 15:14:21

凸包问题是计算几何的核心问题,并且凸包问题的研究已经持续了好多年,这中间涌现出了一大批优秀的算法。

凸包问题的最优解法是Graham Scan算法,该算法可以保证在最差情况下也能在O(nlogn)的时间复杂度求出结果。

Graham Scan算法的核心思路有两个步骤:

1. 预处理:将所有的点按照某个给定的点根据夹角进行排序;

2. 在排序好的结果上,按照顺序逆时针依次进行判断(to left test),将符合条件的节点加入栈中;

在具体实现的时候有一个非常好用的trick,就是不直接对夹角进行排序,而是假定在 +inf 和 -inf 有两个点,那么我们只需要根据x轴进行排序,就可以得到它们相对于两个无穷远点的夹角排序。

这样我们就可以直接使用第二步的递推迭代得到upper hull和lower hull,最后将这两个结果拼接起来就是最终的结果。

下面根据一条leetcode的题目来具体看下代码实现。

问题描述

问题求解

    public int[][] outerTrees(int[][] points) {
if (points.length <= 3) return points;
int n = points.length;
Arrays.sort(points, new Comparator<int[]>(){
public int compare(int[] o1, int[] o2) {
return o1[0] == o2[0] ? o1[1] - o2[1] : o1[0] - o2[0];
}
});
Stack<int[]> upper = new Stack<>();
Stack<int[]> lower = new Stack<>();
Stack<int[]> left = new Stack<>(); upper.add(points[n - 1]);
upper.add(points[n - 2]);
lower.add(points[0]);
lower.add(points[1]); for (int i = 0; i < n - 2; i++) left.add(points[i]);
while (!left.isEmpty()) {
int[] curr = left.pop();
if (upper.size() == 1) {
upper.add(curr);
continue;
}
int[] p2 = upper.pop();
int[] p1 = upper.pop();
if (to_left_test(p1, p2, curr)) {
upper.add(p1);
upper.add(p2);
upper.add(curr);
}
else {
upper.add(p1);
left.add(curr);
}
} for (int i = n - 1; i > 1; i--) left.add(points[i]);
while (!left.isEmpty()) {
int[] curr = left.pop();
if (lower.size() == 1) {
lower.add(curr);
continue;
}
int[] p2 = lower.pop();
int[] p1 = lower.pop();
if (to_left_test(p1, p2, curr)) {
lower.add(p1);
lower.add(p2);
lower.add(curr);
}
else {
lower.add(p1);
left.add(curr);
}
} Set<int[]> set = new HashSet<>();
set.addAll(upper);
set.addAll(lower);
int[][] res = new int[set.size()][2];
int idx = 0;
for (int[] p : set) {
res[idx][0] = p[0];
res[idx][1] = p[1];
idx += 1;
}
return res;
} private boolean to_left_test(int[] p1, int[] p2, int[] p3) {
return p1[0] * p2[1] + p1[1] * p3[0] + p2[0] * p3[1] -
p2[1] * p3[0] - p1[1] * p2[0] - p1[0] * p3[1] >= 0;
}

  

凸包问题 Graham Scan的更多相关文章

  1. 凸包问题——Graham Scan

    Graham Scan 概述: 对于凸多边形的定义不在这里做详细叙述,这里给出算法的实现原理. Step 1: 找出x值最小的点的集合,从其中找出y值最小的点作为初始点 Step 2: 获得新序列后, ...

  2. Graham Scan凸包算法

    获得凸包的算法可以算是计算几何中最基础的算法之一了.寻找凸包的算法有很多种,Graham Scan算法是一种十分简单高效的二维凸包算法,能够在O(nlogn)的时间内找到凸包. 首先介绍一下二维向量的 ...

  3. 凸包Graham Scan算法实现

    凸包算法实现点集合中搜索凸包顶点的功能,可以处理共线情况,可以输出共线点也可以不输出而只输出凸包顶点.经典的Graham Scan算法,点排序使用极角排序方式,并对共线情况做特殊处理.一般算法是将共线 ...

  4. 凸包模板——Graham扫描法

    凸包模板--Graham扫描法 First 标签: 数学方法--计算几何 题目:洛谷P2742[模板]二维凸包/[USACO5.1]圈奶牛Fencing the Cows yyb的讲解:https:/ ...

  5. 计算几何--求凸包模板--Graham算法--poj 1113

    Wall Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 28157   Accepted: 9401 Description ...

  6. 凸包入门(Graham扫描法)(A - Wall POJ - 1113)

    题目链接:https://cn.vjudge.net/contest/276359#problem/A 题目大意:有一个国王,要在自己的城堡周围建立围墙,要求围墙能把城堡全部围起来,并且围墙距离城堡的 ...

  7. poj1113Wall 求凸包周长 Graham扫描法

    #include<iostream> #include<algorithm> #include<cmath> using namespace std; typede ...

  8. HDU 1348 Wall ( 凸包周长 )

    链接:传送门 题意:给出二维坐标轴上 n 个点,这 n 个点构成了一个城堡,国王想建一堵墙,城墙与城堡之间的距离总不小于一个数 L ,求城墙的最小长度,答案四舍五入 思路:城墙与城堡直线长度是相等的, ...

  9. 计算几何(一):凸包问题(Convex Hull)

    引言 首先介绍下什么是凸包?如下图: 在一个二维坐标系中,有若干点杂乱排列着,将最外层的点连接起来构成的凸多边型,它能包含给定的所有的点,这个多边形就是凸包. 实际上可以理解为用一个橡皮筋包含住所有给 ...

随机推荐

  1. Github 绑定域名添加https的方法 2019年9月更新

    官方教程 https://help.github.com/en/articles/using-a-custom-domain-with-github-pages 打开 https://github.c ...

  2. FPGA小白学习之路(4)PLL中的locked信号解析(转)

    ALTPLL中的areset,locked的使用 转自:http://www.360doc.com/content/13/0509/20/9072830_284220258.shtml 今天对PLL中 ...

  3. 大厂面试题:集群部署时的分布式 session 如何实现?

    面试官心理分析 面试官问了你一堆 dubbo 是怎么玩儿的,你会玩儿 dubbo 就可以把单块系统弄成分布式系统,然后分布式之后接踵而来的就是一堆问题,最大的问题就是分布式事务.接口幂等性.分布式锁, ...

  4. iOS开发 - 设立UIButton的Image为Aspect Fit

    Button setImage设置的图片默认是会拉伸缩放的,如果我想要Aspect Fit的效果,要如何做呢?一开始我想到了用contentMode属性,很可惜不起作用.后来我发现button有一个i ...

  5. idea创建django项目

    1.环境.版本 os:windows10 ide:idea python:2.7 django:1.11.25 其他的python.django不确定这么弄会不会有其他问题. 2.python 官网下 ...

  6. 浅谈Spring框架

    一.Spring简介 Spring 是一个开源框架,是为了解决企业应用程序开发复杂性而创建的.框架的主要优势之一就是其分层架构, 分层架构允许您选择使用哪一个组件,同时为 J2EE 应用程序开发提供集 ...

  7. 分享一次C#调用Delphi编写Dll程序

    1.前言: 最近接手了一个项目需要和Delphi语言编写的一个系统进行一些接口的对接,数据在传输过程中采用Des加密方式,因为Delphi 平台的加密方式和C#平台的加密方式不互通,所以采用的方式是C ...

  8. flask 模型一对多个人理解

    在modle中创建两个模型表 class User(db.Model): id = db.Column(db.Integer,primary_key=True,autoincrement=True) ...

  9. scrapycrawl 爬取笔趣阁小说

    前言 第一次发到博客上..不太会排版见谅 最近在看一些爬虫教学的视频,有感而发,大学的时候看盗版小说网站觉得很能赚钱,心想自己也要搞个,正好想爬点小说能不能试试做个网站(网站搭建啥的都不会...) 站 ...

  10. [Python] iupdatable包:File模块使用介绍

    一.简介 文件模块主要是对常见的文件读写功能进行了封装,默认使用UTF8(utf_8_sig)格式编码,实现一行代码读写文件. 二.简单示例 安装 iupdatable 包 pip install - ...