Skip to content

Commit 03714d3

Browse files
committed
feat: add solutions to lc problem: No.0587
No.0587.Erect the Fence
1 parent 84058c3 commit 03714d3

File tree

6 files changed

+450
-2
lines changed

6 files changed

+450
-2
lines changed

solution/0500-0599/0587.Erect the Fence/README.md

Lines changed: 165 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,22 +53,186 @@
5353

5454
<!-- 这里可写通用的实现逻辑 -->
5555

56+
**方法一:Andrew 算法**
57+
58+
原理:
59+
60+
利用夹角,让整个图形保持左转。先将最左边的前两个点加入栈中,每次加入新点时判断是否左拐(叉积大于 0),如果是就将新点直接加入;如果不是,就弹出栈顶,直到左拐,将新点加入栈中。
61+
62+
流程:
63+
64+
1. 将所有点 `(x, y)` 进行排序,以 x 为第一关键字,y 为第二关键字升序排序;
65+
1. 先从左至右维护凸包的下半部分,然后再从右至左维护上半部分;
66+
1. 将第一个点放入栈中,这个点一定时凸包的最左边的点了,是不会清理掉的,然后再将第二个点放入栈中。当栈中元素大于等于 2 的时候,就要判断栈顶元素是否还要保留:
67+
- 如果新点在栈顶元素和次栈顶元素所组成的直线的逆时针方向上,那么直接将新点加入栈中;
68+
- 否则,将栈顶元素不断弹出,直至新点的位置出现在栈顶元素与次栈顶元素所在直线的逆时针方向。
69+
70+
这个过程,是从左往右走的,并且得到的凸包是凸壳的下半部分。求上半部分的时候,从右往左遍历。
71+
72+
时间复杂度 O(nlogn)。
73+
5674
<!-- tabs:start -->
5775

5876
### **Python3**
5977

6078
<!-- 这里可写当前语言的特殊实现逻辑 -->
6179

6280
```python
63-
81+
class Solution:
82+
def outerTrees(self, trees: List[List[int]]) -> List[List[int]]:
83+
def cross(i, j, k):
84+
a, b, c = trees[i], trees[j], trees[k]
85+
return (b[0] - a[0]) * (c[1] - b[1]) - (b[1] - a[1]) * (c[0] - b[0])
86+
87+
n = len(trees)
88+
if n < 4:
89+
return trees
90+
trees.sort()
91+
vis = [False] * n
92+
stk = [0]
93+
for i in range(1, n):
94+
while len(stk) > 1 and cross(stk[-2], stk[-1], i) < 0:
95+
vis[stk.pop()] = False
96+
vis[i] = True
97+
stk.append(i)
98+
m = len(stk)
99+
for i in range(n - 2, -1, -1):
100+
if vis[i]:
101+
continue
102+
while len(stk) > m and cross(stk[-2], stk[-1], i) < 0:
103+
stk.pop()
104+
stk.append(i)
105+
stk.pop()
106+
return [trees[i] for i in stk]
64107
```
65108

66109
### **Java**
67110

68111
<!-- 这里可写当前语言的特殊实现逻辑 -->
69112

70113
```java
114+
class Solution {
115+
public int[][] outerTrees(int[][] trees) {
116+
int n = trees.length;
117+
if (n < 4) {
118+
return trees;
119+
}
120+
Arrays.sort(trees, (a, b) -> {
121+
return a[0] == b[0] ? a[1] - b[1] : a[0] - b[0];
122+
});
123+
boolean[] vis = new boolean[n];
124+
int[] stk = new int[n + 10];
125+
int cnt = 1;
126+
for (int i = 1; i < n; ++i) {
127+
while (cnt > 1 && cross(trees[stk[cnt - 1]], trees[stk[cnt - 2]], trees[i]) < 0) {
128+
vis[stk[--cnt]] = false;
129+
}
130+
vis[i] = true;
131+
stk[cnt++] = i;
132+
}
133+
int m = cnt;
134+
for (int i = n - 1; i >= 0; --i) {
135+
if (vis[i]) {
136+
continue;
137+
}
138+
while (cnt > m && cross(trees[stk[cnt - 1]], trees[stk[cnt - 2]], trees[i]) < 0) {
139+
--cnt;
140+
}
141+
stk[cnt++] = i;
142+
}
143+
int[][] ans = new int[cnt - 1][2];
144+
for (int i = 0; i < ans.length; ++i) {
145+
ans[i] = trees[stk[i]];
146+
}
147+
return ans;
148+
}
149+
150+
private int cross(int[] a, int[] b, int[] c) {
151+
return (b[0] - a[0]) * (c[1] - b[1]) - (b[1] - a[1]) * (c[0] - b[0]);
152+
}
153+
}
154+
```
155+
156+
### **C++**
157+
158+
```cpp
159+
class Solution {
160+
public:
161+
vector<vector<int>> outerTrees(vector<vector<int>>& trees) {
162+
int n = trees.size();
163+
if (n < 4) return trees;
164+
sort(trees.begin(), trees.end());
165+
vector<int> vis(n);
166+
vector<int> stk(n + 10);
167+
int cnt = 1;
168+
for (int i = 1; i < n; ++i)
169+
{
170+
while (cnt > 1 && cross(trees[stk[cnt - 1]], trees[stk[cnt - 2]], trees[i]) < 0) vis[stk[--cnt]] = false;
171+
vis[i] = true;
172+
stk[cnt++] = i;
173+
}
174+
int m = cnt;
175+
for (int i = n - 1; i >= 0; --i)
176+
{
177+
if (vis[i]) continue;
178+
while (cnt > m && cross(trees[stk[cnt - 1]], trees[stk[cnt - 2]], trees[i]) < 0) --cnt;
179+
stk[cnt++] = i;
180+
}
181+
vector<vector<int>> ans;
182+
for (int i = 0; i < cnt - 1; ++i) ans.push_back(trees[stk[i]]);
183+
return ans;
184+
}
185+
186+
int cross(vector<int>& a, vector<int>& b, vector<int>& c) {
187+
return (b[0] - a[0]) * (c[1] - b[1]) - (b[1] - a[1]) * (c[0] - b[0]);
188+
}
189+
};
190+
```
71191

192+
### **Go**
193+
194+
```go
195+
func outerTrees(trees [][]int) [][]int {
196+
n := len(trees)
197+
if n < 4 {
198+
return trees
199+
}
200+
sort.Slice(trees, func(i, j int) bool {
201+
if trees[i][0] == trees[j][0] {
202+
return trees[i][1] < trees[j][1]
203+
}
204+
return trees[i][0] < trees[j][0]
205+
})
206+
cross := func(i, j, k int) int {
207+
a, b, c := trees[i], trees[j], trees[k]
208+
return (b[0]-a[0])*(c[1]-b[1]) - (b[1]-a[1])*(c[0]-b[0])
209+
}
210+
vis := make([]bool, n)
211+
stk := []int{0}
212+
for i := 1; i < n; i++ {
213+
for len(stk) > 1 && cross(stk[len(stk)-1], stk[len(stk)-2], i) < 0 {
214+
vis[stk[len(stk)-1]] = false
215+
stk = stk[:len(stk)-1]
216+
}
217+
vis[i] = true
218+
stk = append(stk, i)
219+
}
220+
m := len(stk)
221+
for i := n - 1; i >= 0; i-- {
222+
if vis[i] {
223+
continue
224+
}
225+
for len(stk) > m && cross(stk[len(stk)-1], stk[len(stk)-2], i) < 0 {
226+
stk = stk[:len(stk)-1]
227+
}
228+
stk = append(stk, i)
229+
}
230+
var ans [][]int
231+
for i := 0; i < len(stk)-1; i++ {
232+
ans = append(ans, trees[stk[i]])
233+
}
234+
return ans
235+
}
72236
```
73237

74238
### **...**

solution/0500-0599/0587.Erect the Fence/README_EN.md

Lines changed: 147 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,159 @@
4242
### **Python3**
4343

4444
```python
45-
45+
class Solution:
46+
def outerTrees(self, trees: List[List[int]]) -> List[List[int]]:
47+
def cross(i, j, k):
48+
a, b, c = trees[i], trees[j], trees[k]
49+
return (b[0] - a[0]) * (c[1] - b[1]) - (b[1] - a[1]) * (c[0] - b[0])
50+
51+
n = len(trees)
52+
if n < 4:
53+
return trees
54+
trees.sort()
55+
vis = [False] * n
56+
stk = [0]
57+
for i in range(1, n):
58+
while len(stk) > 1 and cross(stk[-2], stk[-1], i) < 0:
59+
vis[stk.pop()] = False
60+
vis[i] = True
61+
stk.append(i)
62+
m = len(stk)
63+
for i in range(n - 2, -1, -1):
64+
if vis[i]:
65+
continue
66+
while len(stk) > m and cross(stk[-2], stk[-1], i) < 0:
67+
stk.pop()
68+
stk.append(i)
69+
stk.pop()
70+
return [trees[i] for i in stk]
4671
```
4772

4873
### **Java**
4974

5075
```java
76+
class Solution {
77+
public int[][] outerTrees(int[][] trees) {
78+
int n = trees.length;
79+
if (n < 4) {
80+
return trees;
81+
}
82+
Arrays.sort(trees, (a, b) -> {
83+
return a[0] == b[0] ? a[1] - b[1] : a[0] - b[0];
84+
});
85+
boolean[] vis = new boolean[n];
86+
int[] stk = new int[n + 10];
87+
int cnt = 1;
88+
for (int i = 1; i < n; ++i) {
89+
while (cnt > 1 && cross(trees[stk[cnt - 1]], trees[stk[cnt - 2]], trees[i]) < 0) {
90+
vis[stk[--cnt]] = false;
91+
}
92+
vis[i] = true;
93+
stk[cnt++] = i;
94+
}
95+
int m = cnt;
96+
for (int i = n - 1; i >= 0; --i) {
97+
if (vis[i]) {
98+
continue;
99+
}
100+
while (cnt > m && cross(trees[stk[cnt - 1]], trees[stk[cnt - 2]], trees[i]) < 0) {
101+
--cnt;
102+
}
103+
stk[cnt++] = i;
104+
}
105+
int[][] ans = new int[cnt - 1][2];
106+
for (int i = 0; i < ans.length; ++i) {
107+
ans[i] = trees[stk[i]];
108+
}
109+
return ans;
110+
}
111+
112+
private int cross(int[] a, int[] b, int[] c) {
113+
return (b[0] - a[0]) * (c[1] - b[1]) - (b[1] - a[1]) * (c[0] - b[0]);
114+
}
115+
}
116+
```
117+
118+
### **C++**
119+
120+
```cpp
121+
class Solution {
122+
public:
123+
vector<vector<int>> outerTrees(vector<vector<int>>& trees) {
124+
int n = trees.size();
125+
if (n < 4) return trees;
126+
sort(trees.begin(), trees.end());
127+
vector<int> vis(n);
128+
vector<int> stk(n + 10);
129+
int cnt = 1;
130+
for (int i = 1; i < n; ++i)
131+
{
132+
while (cnt > 1 && cross(trees[stk[cnt - 1]], trees[stk[cnt - 2]], trees[i]) < 0) vis[stk[--cnt]] = false;
133+
vis[i] = true;
134+
stk[cnt++] = i;
135+
}
136+
int m = cnt;
137+
for (int i = n - 1; i >= 0; --i)
138+
{
139+
if (vis[i]) continue;
140+
while (cnt > m && cross(trees[stk[cnt - 1]], trees[stk[cnt - 2]], trees[i]) < 0) --cnt;
141+
stk[cnt++] = i;
142+
}
143+
vector<vector<int>> ans;
144+
for (int i = 0; i < cnt - 1; ++i) ans.push_back(trees[stk[i]]);
145+
return ans;
146+
}
147+
148+
int cross(vector<int>& a, vector<int>& b, vector<int>& c) {
149+
return (b[0] - a[0]) * (c[1] - b[1]) - (b[1] - a[1]) * (c[0] - b[0]);
150+
}
151+
};
152+
```
51153

154+
### **Go**
155+
156+
```go
157+
func outerTrees(trees [][]int) [][]int {
158+
n := len(trees)
159+
if n < 4 {
160+
return trees
161+
}
162+
sort.Slice(trees, func(i, j int) bool {
163+
if trees[i][0] == trees[j][0] {
164+
return trees[i][1] < trees[j][1]
165+
}
166+
return trees[i][0] < trees[j][0]
167+
})
168+
cross := func(i, j, k int) int {
169+
a, b, c := trees[i], trees[j], trees[k]
170+
return (b[0]-a[0])*(c[1]-b[1]) - (b[1]-a[1])*(c[0]-b[0])
171+
}
172+
vis := make([]bool, n)
173+
stk := []int{0}
174+
for i := 1; i < n; i++ {
175+
for len(stk) > 1 && cross(stk[len(stk)-1], stk[len(stk)-2], i) < 0 {
176+
vis[stk[len(stk)-1]] = false
177+
stk = stk[:len(stk)-1]
178+
}
179+
vis[i] = true
180+
stk = append(stk, i)
181+
}
182+
m := len(stk)
183+
for i := n - 1; i >= 0; i-- {
184+
if vis[i] {
185+
continue
186+
}
187+
for len(stk) > m && cross(stk[len(stk)-1], stk[len(stk)-2], i) < 0 {
188+
stk = stk[:len(stk)-1]
189+
}
190+
stk = append(stk, i)
191+
}
192+
var ans [][]int
193+
for i := 0; i < len(stk)-1; i++ {
194+
ans = append(ans, trees[stk[i]])
195+
}
196+
return ans
197+
}
52198
```
53199

54200
### **...**
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
class Solution {
2+
public:
3+
vector<vector<int>> outerTrees(vector<vector<int>>& trees) {
4+
int n = trees.size();
5+
if (n < 4) return trees;
6+
sort(trees.begin(), trees.end());
7+
vector<int> vis(n);
8+
vector<int> stk(n + 10);
9+
int cnt = 1;
10+
for (int i = 1; i < n; ++i)
11+
{
12+
while (cnt > 1 && cross(trees[stk[cnt - 1]], trees[stk[cnt - 2]], trees[i]) < 0) vis[stk[--cnt]] = false;
13+
vis[i] = true;
14+
stk[cnt++] = i;
15+
}
16+
int m = cnt;
17+
for (int i = n - 1; i >= 0; --i)
18+
{
19+
if (vis[i]) continue;
20+
while (cnt > m && cross(trees[stk[cnt - 1]], trees[stk[cnt - 2]], trees[i]) < 0) --cnt;
21+
stk[cnt++] = i;
22+
}
23+
vector<vector<int>> ans;
24+
for (int i = 0; i < cnt - 1; ++i) ans.push_back(trees[stk[i]]);
25+
return ans;
26+
}
27+
28+
int cross(vector<int>& a, vector<int>& b, vector<int>& c) {
29+
return (b[0] - a[0]) * (c[1] - b[1]) - (b[1] - a[1]) * (c[0] - b[0]);
30+
}
31+
};

0 commit comments

Comments
 (0)