## 题目描述：

LeetCode 587. Erect the Fence

There are some trees, where each tree is represented by (x,y) coordinate in a two-dimensional garden. Your job is to 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. Your task is to help find the coordinates of trees which are exactly located on the fence perimeter.

Example 1:

```Input: [[1,1],[2,2],[2,0],[2,4],[3,3],[4,2]]
Output: [[1,1],[2,0],[4,2],[3,3],[2,4]]
Explanation: ```

Example 2:

```Input: [[1,2],[2,2],[4,2]]
Output: [[1,2],[2,2],[4,2]]
Explanation: Even you only have trees in a line, you need to use rope to enclose them.
```

Note:

1. All trees should be enclosed together. You cannot cut the rope to enclose trees that will separate them in more than one group.
2. All input integers will range from 0 to 100.
3. The garden has at least one tree.
4. All coordinates are distinct.
5. Input points have NO order. No order required for output.

## 题目大意：

1. 所有树应该围在一起。不能围成多个组。
2. 输入整数范围0到100。
3. 花园至少有一棵树。
4. 所有坐标不重复。
5. 输入点坐标无序。输出也不需要有序。

## 解题思路：

```1. 求点集points中的最左下点lb

2. 以lb为原点，对points按照极坐标排序

3. 维护栈stack，初始将points, points压入栈

4. 从2到len(points) - 1遍历各点i

重复弹出栈顶，直到points[-2], points[-1], points[i]非顺时针旋转未止

将points[i]压入栈

## Python代码：

``````# Definition for a point.
# class Point(object):
#     def __init__(self, a=0, b=0):
#         self.x = a
#         self.y = b

class Solution(object):
def outerTrees(self, points):
"""
:type points: List[Point]
:rtype: List[Point]
"""
N = len(points)
if N <= 3: return points
lb = min(points, key = lambda p: (p.y, p.x))
ccw = lambda p1, p2, p3: (p2.x - p1.x) * (p3.y - p1.y) - (p2.y - p1.y) * (p3.x - p1.x)
dsquare = lambda p1, p2: (p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2
cmp = lambda p, q: ccw(lb, q, p) or dsquare(p, lb) - dsquare(q, lb)
points.sort(cmp)
x = N - 1
while x and ccw(lb, points[x], points[x - 1]) == 0: x -= 1
points = points[:x] + points[x:][::-1]
stack = [points, points]
for x in range(2, N):
while len(stack) > 1 and ccw(stack[-2], stack[-1], points[x]) < 0: stack.pop()
stack.append(points[x])
return stack
``````

```首先根据x, y坐标对points从小到大排序

for i = 1, 2, ..., n:
while len(L) > 1 并且 L[-2], L[-1], points[i]非逆时针旋转:
L.pop()
L.append(points[i])

for i = n, n-1, ..., 1:
while len(U) > 1 并且 U[-2], U[-1], points[i]非逆时针旋转:
U.pop()
U.append(P[i])

L + U即为凸包（逆时针顺序）```

## Python代码：

``````# Definition for a point.
# class Point(object):
#     def __init__(self, a=0, b=0):
#         self.x = a
#         self.y = b

class Solution(object):
def outerTrees(self, points):
"""
:type points: List[Point]
:rtype: List[Point]
"""
N = len(points)
if N <= 3: return points
lb = min(points, key = lambda p: (p.y, p.x))
ccw = lambda p1, p2, p3:  (p2.x - p1.x) * (p3.y - p1.y) - (p2.y - p1.y) * (p3.x - p1.x)
points.sort(key = lambda p: (p.x, p.y))
lo = []
for x in range(N):
while len(lo) > 1 and ccw(lo[-2], lo[-1], points[x]) < 0: lo.pop()
lo.append(points[x])
up = []
for x in range(N - 1, -1, -1):
while len(up) > 1 and ccw(up[-2], up[-1], points[x]) < 0: up.pop()
up.append(points[x])
return lo[:-1] + up[:-1]
``````

Pingbacks已关闭。