Hard
Erect the Fence — C++
Full explanation · Time O(nlogn) · Space O(n)
// Time: O(nlogn)
// Space: O(n)
// Monotone Chain Algorithm
// Template: https://en.wikibooks.org/wiki/Algorithm_Implementation/Geometry/Convex_hull/Monotone_chain#C++
class Solution {
public:
vector<vector<int>> outerTrees(vector<vector<int>>& P) {
// 3D cross product of OA and OB vectors, (i.e z-component of their "2D" cross product, but remember that it is not defined in "2D").
// Returns a positive value, if OAB makes a counter-clockwise turn,
// negative for clockwise turn, and zero if the points are collinear.
const auto& cross = [](const vector<int>& O, const vector<int>& A, const vector<int>& B) {
return (A[0] - O[0]) * (B[1] - O[1]) - (A[1] - O[1]) * (B[0] - O[0]);
};
// Returns a list of points on the convex hull in counter-clockwise order.
// Note: the last point in the returned list is the same as the first one.
size_t n = P.size(), k = 0;
if (n <= 3) {
return P;
}
vector<vector<int>> H(2*n);
// Sort points lexicographically
sort(P.begin(), P.end());
// Build lower hull
for (size_t i = 0; i < n; ++i) {
while (k >= 2 && cross(H[k-2], H[k-1], P[i]) < 0) k--; // modified
H[k++] = P[i];
}
// Build upper hull
for (size_t i = n-1, t = k+1; i > 0; --i) {
while (k >= t && cross(H[k-2], H[k-1], P[i-1]) < 0) k--; // modified
H[k++] = P[i-1];
}
H.resize(--k);
if (H[1] == H[k - 1]) { // modified
H.resize(k / 2 + 1);
}
return H;
}
};