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 之间。

花园至少有一棵树。

所有树的坐标都是不同的。

输入的点没有顺序。输出顺序也没有要求。

class Solution {
public int[][] outerTrees(int[][] points) {
Set<int[]> hull = new HashSet<>(); // 如果树的棵数小于 4 ,那么直接返回
if (points.length < 4) {
for (int[] p : points) hull.add(p);
return hull.toArray(new int[hull.size()][]);
} // 找到最左边的点
int leftMost = 0;
for (int i = 0; i < points.length; i++) {
if (points[i][0] < points[leftMost][0]) leftMost = i;
} int p = leftMost;
do {
int q = (p + 1) % points.length; for (int i = 0; i < points.length; i++) {
// 如果 i 点在 pq 线下方,则使用 i 点
if (orientation(points[p], points[i], points[q]) < 0) q = i;
}
for (int i = 0; i < points.length; i++) {
// p、q、i 在同一条线上的情况,并且 i 在 p 和 q 的中间的时候
// 也需要将这个点算进来
if (i != p && i != q
&& orientation(points[p], points[i], points[q]) == 0
&& inBetween(points[p], points[i], points[q])) {
hull.add(points[i]);
}
} hull.add(points[q]);
// 重置 p 为 q,接着下一轮的遍历
p = q;
} while (p != leftMost); return hull.toArray(new int[hull.size()][]);
} // 以下 pq 和 qr 都是向量
// pq * qr > 0 表示 r 点在 pq 线上方
// pq * qr < 0 表示 r 点在 pq 线下方
// pq * qr = 0 表示 p、q、r 一条线
// |(q[0]-p[0]) (q[1]-p[1])|
// pq * qr = | | = (q[0]-p[0]) * (r[1]-q[1]) - (r[0]-q[0]) * (q[1]-p[1])
// |(r[0]-q[0]) (r[1]-q[1])|
private int orientation(int[] p, int[] r, int[] q) {
return (q[0] - p[0]) * (r[1] - q[1]) - (r[0] - q[0]) * (q[1] - p[1]);
} // 判断 r 点是不是在 p 点和 q 点之间,需要考虑以下两种情况:
// 1. q 点在 p 点的左边或者右边
// 2. q 点在 p 点的上边或者下边
private boolean inBetween(int[] p, int[] r, int[] q) {
boolean a = r[0] >= p[0] && r[0] <= q[0] || r[0] <= p[0] && r[0] >= q[0];
boolean b = r[1] >= p[1] && r[1] <= q[1] || r[1] <= p[1] && r[1] >= q[1];
return a && b;
}
}

Java实现 LeetCode 587 安装栅栏(图算法转换成数学问题)的更多相关文章

  1. Leetcode 587.安装栅栏

    安装栅栏 在一个二维的花园中,有一些用 (x, y) 坐标表示的树.由于安装费用十分昂贵,你的任务是先用最短的绳子围起所有的树.只有当所有的树都被绳子包围时,花园才能围好栅栏.你需要找到正好位于栅栏边 ...

  2. 分享非常有用的Java程序 (关键代码)(五)---把 Array 转换成 Map

    原文:分享非常有用的Java程序 (关键代码)(五)---把 Array 转换成 Map import java.util.Map; import org.apache.commons.lang.Ar ...

  3. LeetCode 709. To Lower Case (转换成小写字母)

    题目标签:String 题目让我们把大写字母转换成小写,只要遇到的是大写字母,把它 + 32 变成 小写就可以了. Java Solution: Runtime beats 100.00% 完成日期: ...

  4. 【LeetCode】To Lower Case(转换成小写字母)

    这道题是LeetCode里的第709道题. 题目要求: 实现函数 ToLowerCase(),该函数接收一个字符串参数 str,并将该字符串中的大写字母转换成小写字母,之后返回新的字符串. 示例 1: ...

  5. Java中将0x开头的十六进制字符串转换成十进制整数

    1.Integer.toString(int i) 由于input(输入数据)是以0x开头的字符串,并不是整型.因而在用 String s = Integer.toString(input); 时用会 ...

  6. java算法:统计数字-将数字转换成字符串,然后使用字符串String.valueOf()方法进行判断

    题目: 计算数字 k 在 0 到 n 中的出现的次数,k 可能是 0~9 的一个值. 样例 样例 1: 输入: k = 1, n = 1 输出: 1 解释: 在 [0, 1] 中,我们发现 1 出现了 ...

  7. java调用com组件将office文件转换成pdf

    在非常多企业级应用中都涉及到将office图片转换成pdf进行保存或者公布的场景,由于pdf格式的文档方便进行加密和权限控制(类似于百度文库).总结起来眼下将office文件转换 成pdf的方法主要有 ...

  8. Java实现 LeetCode 552 学生出勤记录 II(数学转换?还是动态规划?)

    552. 学生出勤记录 II 给定一个正整数 n,返回长度为 n 的所有可被视为可奖励的出勤记录的数量. 答案可能非常大,你只需返回结果mod 109 + 7的值. 学生出勤记录是只包含以下三个字符的 ...

  9. java泛型基础、子类泛型不能转换成父类泛型

    参考http://how2j.cn/k/generic/generic-generic/373.html 1.使用泛型的好处:泛型的用法是在容器后面添加<Type>Type可以是类,抽象类 ...

随机推荐

  1. 《深入理解Java虚拟机》第 3 版里面到底多了哪些知识点?本文竟然得到了本书作者的认可!

    这是why的第 47 篇原创文章 荒腔走板 大家好,我是 why.老规矩,先是简短的荒腔走板聊聊生活. 上面的图是前几天拍的,那天晚上下班后,刚刚走进小区就看到了这一轮弯月和旁边那一颗特别特别亮的星星 ...

  2. python小游戏-pygame模块

    一.tkinter模块的GUI 基本上使用tkinter来开发GUI应用需要以下5个步骤: 导入tkinter模块中我们需要的东西. 创建一个顶层窗口对象并用它来承载整个GUI应用. 在顶层窗口对象上 ...

  3. CF#637 D. Nastya and Scoreboard DP

    D. Nastya and Scoreboard 题意 一块电子屏幕上有n个数字. 每个数字是通过这样7个线段显示的,现在你不小心打坏了k个线段,给出打坏之后的n个数字的显示方式,问之前的屏幕表示的最 ...

  4. 初级PLC

    SMB2接收到一个数据即产生一次中断,必须在中断处理程序中将数据从SMB2中读出,依次填表.这是一种效率极低的通讯处理方法,通讯字节多了会影响其它程序的运行. M 是位地址.比如M0.0,M0.1等. ...

  5. [hdu5313]二分图性质,dp

    题意:给定二分图,求添加的最多边数,使得添加之后还是二分图 思路:如果原图可以分成X,Y两个点集,那么边数最多为|X||Y|条.由于|X|+|Y|==n,所以需要使|X|与|Y|尽量接近.先对原图进行 ...

  6. 详解 Spark 中的 Bucketing

    什么是 Bucketing Bucketing 就是利用 buckets(按列进行分桶)来决定数据分区(partition)的一种优化技术,它可以帮助在计算中避免数据交换(avoid data shu ...

  7. iOS事件的响应和传递机制

    跟二狗子哥哥交流的时候,他总说我,说的过程太业余.故 好好学习整理一下.努力不那么业余. 一.事件的产生.传递.响应: 1.事件从父控件依次传递到子控件,寻找最合适的子控件View. 2.寻找最合适的 ...

  8. 修改jupyter默认保存文件的目录

    1.打开 Anaconda Prompt输入命令 jupyter notebook --generate-config 2.可以看到生成了目录及jupyter notebook的配置文件,打开该文件. ...

  9. 深入理解JS中的对象(三):class 的工作原理

    目录 序言 class 是一个特殊的函数 class 的工作原理 class 继承的原型链关系 参考 1.序言 ECMAScript 2015(ES6) 中引入的 JavaScript 类实质上是 J ...

  10. ql自动化测试之路-概述篇

    前言:本节主要讲解自动化测试的基本概述,包括分层自动化测试.自动化测试中用到的工具.以及关于自动化测试的想法 一.分层自动化测试 上图是经典的测试金字塔.用它来形容目前测试投入的价值是比较适合的,同样 ...