Skip to content

587. Erect the Fence

Description

You are given an array trees where trees[i] = [xi, yi] represents the location of a tree in the garden.

Fence the entire garden using the minimum length of rope, as it is expensive. The garden is well-fenced only if all the trees are enclosed.

Return the coordinates of trees that are exactly located on the fence perimeter. You may return the answer in any order.

 

Example 1:

Input: trees = [[1,1],[2,2],[2,0],[2,4],[3,3],[4,2]]
Output: [[1,1],[2,0],[4,2],[3,3],[2,4]]
Explanation: All the trees will be on the perimeter of the fence except the tree at [2, 2], which will be inside the fence.

Example 2:

Input: trees = [[1,2],[2,2],[4,2]]
Output: [[4,2],[2,2],[1,2]]
Explanation: The fence forms a line that passes through all the trees.

 

Constraints:

  • 1 <= trees.length <= 3000
  • trees[i].length == 2
  • 0 <= xi, yi <= 100
  • All the given positions are unique.

 

Solutions

Solution: Monotone Chain Algorithm

  • Time complexity: O(nlogn)
  • Space complexity: O(n)

 

JavaScript

js
/**
 * @param {number[][]} trees
 * @return {number[][]}
 */
const outerTrees = function (trees) {
  const n = trees.length;

  if (n <= 1) return trees;

  const crossProduct = (a, b, c) => {
    const BAx = a[0] - b[0];
    const BAy = a[1] - b[1];
    const BCx = c[0] - b[0];
    const BCy = c[1] - b[1];

    return BAx * BCy - BAy * BCx;
  };

  trees.sort((a, b) => a[0] - b[0] || a[1] - b[1]);

  const lower = [];
  const upper = [];

  for (const point of trees) {
    while (lower.length >= 2 && crossProduct(lower.at(-2), lower.at(-1), point) < 0) {
      lower.pop();
    }
    lower.push(point);
  }

  for (let index = n - 1; index >= 0; index--) {
    const point = trees[index];

    while (upper.length >= 2 && crossProduct(upper.at(-2), upper.at(-1), point) < 0) {
      upper.pop();
    }
    upper.push(point);
  }

  return [...new Set([...lower, ...upper])];
};

Released under the MIT license