0
点赞
收藏
分享

微信扫一扫

LeetCode 587 安装栅栏[凸包算法 Jarvis算法] HERODING的LeetCode之路

在这里插入图片描述
在这里插入图片描述
解题思路:
今日的每日一题是博主第一次接触凸包问题,凸包问题是解决几何中包围问题的重要解法,这里只介绍其中的Jarvis算法。Jarvis算法思想很简单,首先找到凸包上的点(一般从最左边出发)作为p,然后假定一个q,再遍历所有点,用来更新q使得所有点都在pq向量左边,这要通过向量的叉积实现(定义cross函数),叉积大于0则都在左边,小于零在右边,等于零在一条直线上,这时候要把该点直接加入到集合中,遍历过的q要标记为访问,并把p更新为q,如此直到回到起点,则凸包形成,代码如下:

class Solution {
public:
    int cross(vector<int>& p, vector<int>& q,vector<int>& r) {
        return (q[0] - p[0]) * (r[1] - q[1]) - (q[1] - p[1]) * (r[0] - q[0]);
    }

    vector<vector<int>> outerTrees(vector<vector<int>>& trees) {
        int n = trees.size();
        if(n < 4) return trees;
        // 找最左边的点
        int leftMost = 0;
        for(int i = 1; i < n; i ++) {
            if(trees[i][0] < trees[leftMost][0]) {
                leftMost = i;
            }
        }
        vector<vector<int>> res;
        vector<bool> visited(n, false);
        int p = leftMost;
        do {
            int q = (p + 1) % n;
            // 找到在r右边的q
            for(int r = 0; r < n; r ++) {
                // 如果r在pq的右边
                if(cross(trees[p], trees[q], trees[r]) < 0) {
                    q = r;
                }
            }
            // 判断是否有i在pq之间
            for(int i = 0; i < n; i ++) {
                if(visited[i] || i == p || i == q) {
                    continue;
                }
                if(cross(trees[p], trees[q], trees[i]) == 0) {
                    res.emplace_back(trees[i]);
                    visited[i] = true;
                }
            }
            if(!visited[q]) {
                res.emplace_back(trees[q]);
                visited[q] = true;
            }
            p = q;
        } while(p != leftMost); // 最后回归起点
        return res;
    }
};
举报

相关推荐

0 条评论