from typing import List
class Solution:
def outerTrees(self, trees: List[List[int]]) -> List[List[int]]:
def cross(o, a, b):
return (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0])
trees.sort()
n = len(trees)
if n <= 1:
return trees
lower = []
for tree in trees:
while len(lower) >= 2 and cross(lower[-2], lower[-1], tree) < 0:
lower.pop()
lower.append(tree)
upper = []
for tree in reversed(trees):
while len(upper) >= 2 and cross(upper[-2], upper[-1], tree) < 0:
upper.pop()
upper.append(tree)
# Remove last point of each half because it's repeated
result = lower[:-1] + upper[:-1]
# Remove duplicates (colinear points may be added multiple times)
return list(map(list, set(map(tuple, result))))
class Solution {
public:
vector> outerTrees(vector>& trees) {
auto cross = [](vector& o, vector& a, vector& b) {
return (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0]);
};
sort(trees.begin(), trees.end());
int n = trees.size();
if (n <= 1) return trees;
vector> lower, upper;
for (auto& tree : trees) {
while (lower.size() >= 2 && cross(lower[lower.size()-2], lower[lower.size()-1], tree) < 0)
lower.pop_back();
lower.push_back(tree);
}
for (int i = n - 1; i >= 0; --i) {
while (upper.size() >= 2 && cross(upper[upper.size()-2], upper[upper.size()-1], trees[i]) < 0)
upper.pop_back();
upper.push_back(trees[i]);
}
lower.pop_back();
upper.pop_back();
lower.insert(lower.end(), upper.begin(), upper.end());
// Remove duplicates
sort(lower.begin(), lower.end());
lower.erase(unique(lower.begin(), lower.end()), lower.end());
return lower;
}
};
class Solution {
public int[][] outerTrees(int[][] trees) {
Arrays.sort(trees, (a, b) -> a[0] != b[0] ? a[0] - b[0] : a[1] - b[1]);
int n = trees.length;
if (n <= 1) return trees;
List<int[]> lower = new ArrayList<>();
for (int[] tree : trees) {
while (lower.size() >= 2 && cross(lower.get(lower.size()-2), lower.get(lower.size()-1), tree) < 0)
lower.remove(lower.size()-1);
lower.add(tree);
}
List<int[]> upper = new ArrayList<>();
for (int i = n - 1; i >= 0; --i) {
while (upper.size() >= 2 && cross(upper.get(upper.size()-2), upper.get(upper.size()-1), trees[i]) < 0)
upper.remove(upper.size()-1);
upper.add(trees[i]);
}
lower.remove(lower.size()-1);
upper.remove(upper.size()-1);
lower.addAll(upper);
// Remove duplicates
Set<String> seen = new HashSet<>();
List<int[]> res = new ArrayList<>();
for (int[] p : lower) {
String key = p[0] + "," + p[1];
if (seen.add(key)) res.add(p);
}
return res.toArray(new int[res.size()][]);
}
private int cross(int[] o, int[] a, int[] b) {
return (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0]);
}
}
/**
* @param {number[][]} trees
* @return {number[][]}
*/
var outerTrees = function(trees) {
trees.sort((a, b) => a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]);
const cross = (o, a, b) => (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0]);
const n = trees.length;
if (n <= 1) return trees;
const lower = [];
for (const tree of trees) {
while (lower.length >= 2 && cross(lower[lower.length-2], lower[lower.length-1], tree) < 0)
lower.pop();
lower.push(tree);
}
const upper = [];
for (let i = n - 1; i >= 0; --i) {
while (upper.length >= 2 && cross(upper[upper.length-2], upper[upper.length-1], trees[i]) < 0)
upper.pop();
upper.push(trees[i]);
}
lower.pop();
upper.pop();
const result = lower.concat(upper);
// Remove duplicates
const seen = new Set();
const ans = [];
for (const p of result) {
const key = p[0] + ',' + p[1];
if (!seen.has(key)) {
seen.add(key);
ans.push(p);
}
}
return ans;
};
[x, y]
. The fence must be a convex polygon (convex hull) that touches or passes through as many trees as possible, including all trees on the boundary. If multiple valid answers exist, you can return any of them. The solution should not reuse elements, and it must include all points that are on the boundary, even if they are collinear.
trees = [[1,1], [2,2], [2,0], [2,4], [3,3], [4,2]]
.
[[1,1], [2,0], [2,2], [2,4], [3,3], [4,2]]
.[[1,1], [2,0], [4,2], [3,3], [2,4]]
(order may vary).