Skip to content

Commit 11b963d

Browse files
committed
init commit
0 parents  commit 11b963d

File tree

8 files changed

+266
-0
lines changed

8 files changed

+266
-0
lines changed

.github/workflows/go.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
name: Go
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
pull_request:
8+
branches:
9+
- master
10+
jobs:
11+
build_and_test:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- name: Checkout
15+
uses: actions/checkout@v3
16+
- name: Setup Go
17+
uses: actions/setup-go@v3
18+
with:
19+
go-version: 1.16
20+
- name: Build
21+
run: go build -v ./...
22+
- name: Test
23+
run: go test -v -cover ./...
24+
- name: BenchmarkTest
25+
run: go test -benchmem -run=none -bench ^BenchmarkTest sol/sol

.gitignore

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# If you prefer the allow list template instead of the deny list, see community template:
2+
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
3+
#
4+
# Binaries for programs and plugins
5+
*.exe
6+
*.exe~
7+
*.dll
8+
*.so
9+
*.dylib
10+
11+
# Test binary, built with `go test -c`
12+
*.test
13+
14+
# Output of the go coverage tool, specifically when used with LiteIDE
15+
*.out
16+
17+
# Dependency directories (remove the comment below to include it)
18+
# vendor/
19+
20+
# Go workspace file
21+
go.work

.gitlab-ci.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
stages:
2+
- test
3+
build and test:
4+
image: golang:1.16
5+
stage: test
6+
script:
7+
- go build -v ./...
8+
- go test -v -cover ./...
9+
- go test -benchmem -run=none -bench ^BenchmarkTest sol/sol

.husky/pre-commit

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/bin/bash
2+
go test -v -cover ./...

README.md

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
# golang_trapping_rain_water
2+
3+
Given `n` non-negative integers representing an elevation map where the width of each bar is `1`
4+
, compute how much water it can trap after raining.
5+
6+
## Examples
7+
8+
**Example 1:**
9+
10+
![https://assets.leetcode.com/uploads/2018/10/22/rainwatertrap.png](https://assets.leetcode.com/uploads/2018/10/22/rainwatertrap.png)
11+
12+
```
13+
Input: height = [0,1,0,2,1,0,1,3,2,1,2,1]
14+
Output: 6
15+
Explanation: The above elevation map (black section) is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped.
16+
17+
```
18+
19+
**Example 2:**
20+
21+
```
22+
Input: height = [4,2,0,3,2,5]
23+
Output: 9
24+
25+
```
26+
27+
**Constraints:**
28+
29+
- `n == height.length`
30+
- `1 <= n <= 2 * $10^4$`
31+
- `0 <= height[i] <= $10^5$`
32+
33+
## 解析
34+
35+
給定一個非負整數陣列 height
36+
37+
每個height[i] 代表在 i 位置的高度
38+
39+
假設每個 height[i] 寬度是 1 單位長度
40+
41+
如果要在位置 i 累積雨水
42+
43+
需要有存在 0 ≤ k < i , i < j ≤ len(height) - 1 使得 min (height[j], height[k]) > height[i]
44+
45+
且累積的雨水面積 = min (height[j], height[k]) - height[i]
46+
47+
![](https://i.imgur.com/QrMBGDN.png)
48+
49+
要求寫一個演算法算出在給定的 height 中能累積的雨水面積
50+
51+
由雨水累積的條件可以看出
52+
53+
對於每一個位置 i 所能累積的雨水
54+
55+
必須從位置 0 到 i-1 找出一個 k , 使得 height[k]> height[i] 且 是 height[k]從 0 到 i-1 的最大值 leftMax
56+
57+
必須從位置 i+1 到 len(height)-1 找出一個 j , 使得 height[j]> height[i] 且 是 height[j]從 i+1
58+
59+
到 len(height) -1 的 最大值 rightMax
60+
61+
該位置累積的雨水= min(leftMax, rightMax) - height[i]
62+
63+
64+
![](https://i.imgur.com/CE7pcVN.png)
65+
66+
對於這樣的特性可以使用左右兩個 pointer 來做找尋每個當下的 leftMax, rightMax
67+
68+
並且在遇到有符合 min(leftMax,rightMax) > height[i]累加
69+
70+
具體作法如下
71+
72+
初始化 lp =0, rp = len(height) - 1, leftMax =0 , rightMax = 0 , result = 0
73+
74+
當 lp < rp 時做以下運算
75+
76+
當 height[rp] > height[lp] 代表 左界比較少
77+
78+
檢查 height[lp] > leftMax 決定是否需要累積面積
79+
80+
當 height[lp] > leftMax 時 代表不需要累積水位 更新 leftMax = height[lp]
81+
82+
否則 更新 result += leftMax - height[lp] (累積 lp 水位)
83+
84+
更新 lp += 1
85+
86+
當 height[rp] ≤ height[lp] 代表 右界比較少
87+
88+
檢查 height[rp] > rightMax 決定是否需要累積面積
89+
90+
當 height[rp] > rightMax 時 代表不需要累積水位 更新 rightMax = height[rp]
91+
92+
否則 更新 result += rightMax - height[rp] (累積 rp 水位)
93+
94+
更新 rp -= 1
95+
96+
回傳 result
97+
98+
![](https://i.imgur.com/a5Slape.png)
99+
100+
## 程式碼
101+
```go
102+
package sol
103+
104+
func trap(height []int) int {
105+
leftMax, rightMax, result := 0, 0, 0
106+
lp, rp := 0, len(height)-1
107+
for lp < rp {
108+
if height[lp] > height[rp] {
109+
if height[rp] > rightMax {
110+
rightMax = height[rp]
111+
} else {
112+
result += rightMax - height[rp]
113+
}
114+
rp--
115+
} else {
116+
if height[lp] > leftMax {
117+
leftMax = height[lp]
118+
} else {
119+
result += leftMax - height[lp]
120+
}
121+
lp++
122+
}
123+
}
124+
return result
125+
}
126+
127+
```
128+
## 困難點
129+
130+
1. 要思考出能夠累積雨水的條件
131+
2. 要思考出利用 two pointer 來找出每個位置所能累積雨水的關係
132+
3. 要思考出如何做最佳的移動方式,因為只有較短的 height 會影響累積雨水的狀況所以先移動較短的部份
133+
134+
## Solve Point
135+
136+
- [x] 初始化 lp =0, rp = len(height) - 1, leftMax = 0, rightMax = 0, result = 0
137+
- [x] 當 lp < rp 時 做以下計算
138+
- [x] 當 height[lp] > height[rp] 做以下運算 (rp 是比較低的部份 有機會形成 雨水累積)
139+
- [x] 當 height[rp] > rightMax 時, 更新 rightMax = height[rp] (無法累積雨水) 否則更新 result += rightMax - height[rp]
140+
- [x] 更新 rp -= 1
141+
- [x] 當 height[lp] ≤ height[rp] 做以下運算 (lp 是比較低的部份 有機會形成 雨水累積)
142+
- [x] 當 height[lp] > leftMax 時, 更新 leftMax = height[lp] (無法累積雨水) , 否則更新 result += leftMax - height[lp]
143+
- [x] 更新 lp += 1
144+
- [x] 回傳 result

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module sol
2+
3+
go 1.16

sol/solution.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package sol
2+
3+
func trap(height []int) int {
4+
leftMax, rightMax, result := 0, 0, 0
5+
lp, rp := 0, len(height)-1
6+
for lp < rp {
7+
if height[lp] > height[rp] {
8+
if height[rp] > rightMax {
9+
rightMax = height[rp]
10+
} else {
11+
result += rightMax - height[rp]
12+
}
13+
rp--
14+
} else {
15+
if height[lp] > leftMax {
16+
leftMax = height[lp]
17+
} else {
18+
result += leftMax - height[lp]
19+
}
20+
lp++
21+
}
22+
}
23+
return result
24+
}

sol/solution_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package sol
2+
3+
import "testing"
4+
5+
func BenchmarkTest(b *testing.B) {
6+
height := []int{0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1}
7+
for idx := 0; idx < b.N; idx++ {
8+
trap(height)
9+
}
10+
}
11+
func Test_trap(t *testing.T) {
12+
type args struct {
13+
height []int
14+
}
15+
tests := []struct {
16+
name string
17+
args args
18+
want int
19+
}{
20+
{
21+
name: "height = [0,1,0,2,1,0,1,3,2,1,2,1]",
22+
args: args{height: []int{0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1}},
23+
want: 6,
24+
},
25+
{
26+
name: "height = [4,2,0,3,2,5]",
27+
args: args{height: []int{4, 2, 0, 3, 2, 5}},
28+
want: 9,
29+
},
30+
}
31+
for _, tt := range tests {
32+
t.Run(tt.name, func(t *testing.T) {
33+
if got := trap(tt.args.height); got != tt.want {
34+
t.Errorf("trap() = %v, want %v", got, tt.want)
35+
}
36+
})
37+
}
38+
}

0 commit comments

Comments
 (0)