Leetcode 587.安装栅栏
安装栅栏
在一个二维的花园中,有一些用 (x, y) 坐标表示的树。由于安装费用十分昂贵,你的任务是先用最短的绳子围起所有的树。只有当所有的树都被绳子包围时,花园才能围好栅栏。你需要找到正好位于栅栏边界上的树的坐标。
示例 1:
输入: [[1,1],[2,2],[2,0],[2,4],[3,3],[4,2]]
输出: [[1,1],[2,0],[4,2],[3,3],[2,4]]
解释:

示例 2:
输入: [[1,2],[2,2],[4,2]]
输出: [[1,2],[2,2],[4,2]]
解释:

即使树都在一条直线上,你也需要先用绳子包围它们。
注意:
- 所有的树应当被围在一起。你不能剪断绳子来包围树或者把树分成一组以上。
- 输入的整数在 0 到 100 之间。
- 花园至少有一棵树。
- 所有树的坐标都是不同的。
- 输入的点没有顺序。输出顺序也没有要求。
Graham扫描法
我给了它一个新名字,边界扫描法。用到的性质和解法二密切相关,首先也需要对某个维度进行从小达到排序。这样我们就能确定其中一个顶点了,我们选择横坐标最小的那个点作为整个坐标的原点。








算法步骤:
1. 把所有点放在二维坐标系中,则纵坐标最小的点一定是凸包上的点,如图中的P0。
2. 把所有点的坐标平移一下,使 P0 作为原点,如上图。
3. 计算各个点相对于 P0 的幅角 α ,按从小到大的顺序对各个点排序。当 α 相同时,距离 P0 比较近的排在前面。例如上图得到的结果为 P1,P2,P3,P4,P5,P6,P7,P8。我们由几何知识可以知道,结果中第一个点 P1 和最后一个点 P8 一定是凸包上的点。
(以上是准备步骤,以下开始求凸包)
以上,我们已经知道了凸包上的第一个点 P0 和第二个点 P1,我们把它们放在栈里面。现在从步骤3求得的那个结果里,把 P1 后面的那个点拿出来做当前点,即 P2 。接下来开始找第三个点:
4. 连接P0和栈顶的那个点,得到直线 L 。看当前点是在直线 L 的右边还是左边。如果在直线的右边就执行步骤5;如果在直线上,或者在直线的左边就执行步骤6。
5. 如果在右边,则栈顶的那个元素不是凸包上的点,把栈顶元素出栈。执行步骤4。
6. 当前点是凸包上的点,把它压入栈,执行步骤7。
7. 检查当前的点 P2 是不是步骤3那个结果的最后一个元素。是最后一个元素的话就结束。如果不是的话就把 P2 后面那个点做当前点,返回步骤4。


public class Solution {
public int orientation(Point p, Point q, Point r) {
return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
}
public int distance(Point p, Point q) {
return (p.x - q.x) * (p.x - q.x) + (p.y - q.y) * (p.y - q.y);
}
private static Point bottomLeft(Point[] points) {
Point bottomLeft = points[0];
for (Point p: points)
if (p.y < bottomLeft.y)
bottomLeft = p;
return bottomLeft;
}
public List <Point> outerTrees(Point[] points) {
if (points.length <= 1)
return Arrays.asList(points);
Point bm = bottomLeft(points);
Arrays.sort(points, new Comparator< Point >() {
public int compare(Point p, Point q) {
double diff = orientation(bm, p, q) - orientation(bm, q, p);
if (diff == 0)
return distance(bm, p) - distance(bm, q);
else
return diff > 0 ? 1 : -1;
}
});
int i = points.length - 1;
while (i >= 0 && orientation(bm, points[points.length - 1], points[i]) == 0)
i--;
for (int l = i + 1, h = points.length - 1; l < h; l++, h--) {
Point temp = points[l];
points[l] = points[h];
points[h] = temp;
}
Stack < Point > stack = new Stack< >();
stack.push(points[0]);
stack.push(points[1]);
for (int j = 2; j < points.length; j++) {
Point top = stack.pop();
while (orientation(stack.peek(), top, points[j]) > 0)
top = stack.pop();
stack.push(top);
stack.push(points[j]);
}
return new ArrayList<>(stack);
}
}
Leetcode 587.安装栅栏的更多相关文章
- Java实现 LeetCode 587 安装栅栏(图算法转换成数学问题)
587. 安装栅栏 在一个二维的花园中,有一些用 (x, y) 坐标表示的树.由于安装费用十分昂贵,你的任务是先用最短的绳子围起所有的树.只有当所有的树都被绳子包围时,花园才能围好栅栏.你需要找到正好 ...
- leetcode 587. Erect the Fence 凸包的计算
leetcode.587.Erect the Fence 凸包问题.好像是我在leetcode做的第一个凸包问题吧. 第一次做,涉及到的东西还是蛮多的.有一个东西很重要,就是已知一个点和一个矢量,求这 ...
- [Swift]LeetCode587. 安装栅栏 | Erect the Fence
There are some trees, where each tree is represented by (x,y) coordinate in a two-dimensional garden ...
- Swift LeetCode 目录 | Catalog
请点击页面左上角 -> Fork me on Github 或直接访问本项目Github地址:LeetCode Solution by Swift 说明:题目中含有$符号则为付费题目. 如 ...
- C#LeetCode刷题-几何
几何篇 # 题名 刷题 通过率 难度 587 安装栅栏 21.5% 困难 892 三维形体的表面积 C#LeetCode刷题之#892-三维形体的表面积(Surface Area of 3D Sh ...
- leetcode难题
4 寻找两个有序数组的中位数 35.9% 困难 10 正则表达式匹配 24.6% 困难 23 合并K个排序链表 47.4% 困难 25 K ...
- IDEA安装leetcode editor插件
leetcode > https://leetcode-cn.com/ 本地idea刷题可以直接同步提交,测试等相关操作 需要安装leetcode editor插件 1.idea setting ...
- 工具推荐--刷LeetCode的神器
本文首发于微信公众号:[坂本先生],文章地址为: https://mp.weixin.qq.com/s/vHv5hO8nils_g2VSKwu1Cg如有转载请标明出处 今天给大家安利一款快速刷Leet ...
- IDEA2020.1使用LeetCode插件运行并调试本地样例
环境: idea2020.1 插件: LeetCode-editor 6.7 一.IDEA安装LeetCode插件 安装完成重启idea 打开插件 URL可以选择国服和世界服.LoginName和Pa ...
随机推荐
- php生成纯数字、字母数字、图片、纯汉字的随机数验证码
现在讲开始通过PHP生成各种验证码旅途,新手要开车了,请刷卡! 首先,我们开始先生成一个放验证码的背景图片 注:没有Imagejpg()这个函数,只有imagepng()函数 imagecreatet ...
- RTMP,RTMPT,RTMPS,RTMPE,RTMPTE协议的介绍
1. AMF AMF(是Action Message Format的缩写)是在flash和flex中与远程服务端交换数据的一种格式.它是二进制格式,Flash应用与服务端或数据库通过RPC交换数据时, ...
- Copy Failed Error Access to fobidden
使用SVN的branch/tag命令来切包时,报出了一下错误提示 就这个错误,调了整整一天,如果你也遇到了类似问题,我真心希望下面解决问题的过程能帮助到你:D 解决过程: 1.网上查了很多帖子,发现跟 ...
- 2018.2.5 PHP如何写好一个程序用框架
随着PHP标准和Composer包管理工具的面世,普通开发者撸一个框架已经不再是什么难事了. 无论是路由管理.ORM管理.还是视图渲染都有许许多多优秀的包可以使用.我们就像堆积木一样把这些包用comp ...
- window下安装ubuntu(ubuntu可删除)
进入ububtu13.04的安装界面,这里我们选择了“中文(简体)”,然后单击安装: 下图是现场拍的: 出现如下图时,请根据需要选择,然后单击“继续” , 接下来会出现问你是否要连接网络,我们选择 ...
- 02-CSS基础与进阶-day13_2018-09-21-20-05-21
css3动画 @keyframes 动画名 { 0% { } 100% { } } 元素执行动画 animation: 动画名 运动时间 运动曲线 01运动的汽车.html <!DOCTYPE ...
- 微信小程序的开发——01小程序的执行流程是怎样的?
作者:叶小钗 转载至:https://www.cnblogs.com/yexiaochai/p/9346043.html 我们这边最近一直在做基础服务,这一切都是为了完善技术体系,这里对于前端来说便是 ...
- 洛谷P3371单源最短路径SPFA算法
SPFA同样是一种基于贪心的算法,看过之前一篇blog的读者应该可以发现,SPFA和堆优化版的Dijkstra如此的相似,没错,但SPFA有一优点是Dijkstra没有的,就是它可以处理负边的情况. ...
- tp5依赖注入(自动实例化):解决了像类中的方法传对象的问题
app\index\Demo1.php namespace app\index\controller; /* 容器与依赖注入的原理 ----------------------------- 1.任何 ...
- thinkphp 3.2.3 - Think.class.php 解析
class Think { public static function start() { // 注册AUTOLOAD方法 spl_autoload_register('Think\Think::a ...