文章目录
- 1. 题目
- 2. 解题
1. 题目
在一个二维的花园中,有一些用 (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 之间。
花园至少有一棵树。
所有树的坐标都是不同的。
输入的点没有顺序。输出顺序也没有要求。
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/erect-the-fence
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
LintCode 题目地址:https://www.lintcode.com/problem/erect-the-fence/description
2. 解题
- 将所有的点按 x,y 排序
- 先将前面两个点加入答案,正序检查当前点跟答案里最后两个点组成的向量的叉积指向是否满足凸包要求,不满足,则将答案里最后一个点弹出,满足,则将点压入答案。得到下边界
- 然后逆序检查,得到上边界,然后去重
下图考虑的是下边界,正序遍历的情况
/*** Definition for a point.* struct Point {* int x;* int y;* Point() : x(0), y(0) {}* Point(int a, int b) : x(a), y(b) {}* };*/
// LintCode 输入格式不太一样
struct cmp{bool operator()(const Point a, const Point b) const{return a.x<b.x || (a.x==b.x && a.y<b.y);}
};
class Solution {
public:vector<Point> outerTrees(vector<Point> &points) {// write your code heresort(points.begin(), points.end(),[&](auto &a, auto &b){return a.x < b.x || (a.x == b.x && a.y < b.y);});vector<Point> ans;for(int i = 0; i < points.size(); ++i){while(ans.size()>=2 && dot(ans[ans.size()-2], ans[ans.size()-1],points[i]) < 0)ans.pop_back();ans.push_back(points[i]);}for(int i = points.size()-1; i >= 0; --i){while(ans.size()>=2 && dot(ans[ans.size()-2], ans[ans.size()-1],points[i]) < 0)ans.pop_back();ans.push_back(points[i]);}set<Point, cmp> set(ans.begin(), ans.end());vector<Point> res(set.begin(), set.end());return res;}int dot(Point& a, Point& b, Point& c){int x1 = b.x-a.x;int y1 = b.y-a.y;int x2 = c.x-b.x;int y2 = c.y-b.y;return x1*y2-x2*y1;}
};
// LeetCode
class Solution {
public:vector<vector<int>> outerTrees(vector<vector<int>>& points) {sort(points.begin(), points.end());vector<vector<int>> ans;for(int i = 0; i < points.size(); ++i){while(ans.size()>=2 && dot(ans[ans.size()-2], ans[ans.size()-1],points[i]) < 0)ans.pop_back();ans.push_back(points[i]);}for(int i = points.size()-1; i >= 0; --i){while(ans.size()>=2 && dot(ans[ans.size()-2], ans[ans.size()-1],points[i]) < 0)ans.pop_back();ans.push_back(points[i]);}set<vector<int>> set(ans.begin(), ans.end());vector<vector<int>> res(set.begin(), set.end());return res;}int dot(vector<int>& a, vector<int>& b, vector<int>& c){int x1 = b[0]-a[0];int y1 = b[1]-a[1];int x2 = c[0]-b[0];int y2 = c[1]-b[1];return x1*y2-x2*y1;}
};
// 80 ms 22.9 MB C++
我的CSDN博客地址 https://michael.blog.csdn.net/
长按或扫码关注我的公众号(Michael阿明),一起加油、一起学习进步!