Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 0 additions & 133 deletions .github/workflows/pr-preview.yml

This file was deleted.

142 changes: 142 additions & 0 deletions 42. Trapping Rain Water.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
## step1 とりあえず解く
- 計算量
- 時間:O(N^2)
- 空間:O(N)
- 解けなかったが考えたアプローチとしては
- 与えられた配列から、前後より高いBarを探してそのindexを配列に保持する
- index配列からその高いBarの間に溜まっている水の堆積を計算する
- このアプローチがうまく行かないケース
- input
- height=[4,2,0,3,2,5]
- 局所的な高いBarしか探していないため上記のような入力では正しい回答が得られない
- 上記アプローチをもとに実装した内容

```java
class Solution {
public int trap(int[] height) {
List<Integer> heigherBarIndex = new ArrayList<>();
for (int i = 0; i < height.length - 1; i++) {
if (i == 0 && height[i] > height[i+1]) {
heigherBarIndex.add(i);
continue;
}
if (i > 0 && height[i] > height[i-1] && height[i] > height[i+1]) {
heigherBarIndex.add(i);
}
}
int ans = 0;
for (int i = 0; i < heigherBarIndex.size() - 1; i++) {
int size = Math.min(height[heigherBarIndex.get(i)], height[heigherBarIndex.get(i+1)])
* (heigherBarIndex.get(i + 1) - heigherBarIndex.get(i) -1);
int start = heigherBarIndex.get(i) + 1;
while (start < heigherBarIndex.get(i+1)){
size -= height[start];
start++;
}
ans += size;
}
return ans;
}
}

```

## step2 他の人の回答を見る
- 計算量
- 時間:O(N)
- 空間:O(N)
- 考え方としては、そのBarにためられる水の量は「そのBarから見た時のmin(leftMax, rightMax)-そのBarの高さ」
- 上記計算が負の場合は水が溢れるのでたまらないと判断
- 各Barに対してleftMax, rightMaxを配列で保持し最後に上記考え方で算出する

```java
public class Solution {
public int trap(int[] height) {
int n = height.length;
if (n == 0) {
return 0;
}

int[] leftMax = new int[n];
int[] rightMax = new int[n];

leftMax[0] = height[0];
for (int i = 1; i < n; i++) {
leftMax[i] = Math.max(leftMax[i - 1], height[i]);
}

rightMax[n - 1] = height[n - 1];
for (int i = n - 2; i >= 0; i--) {
rightMax[i] = Math.max(rightMax[i + 1], height[i]);
}

int res = 0;
for (int i = 0; i < n; i++) {
res += Math.min(leftMax[i], rightMax[i]) - height[i];
}
return res;
}
}
```

- 計算量
- 時間:O(N)
- 空間:O(1)
- Two Pointerで各Barに対してleftMax, rightMaxを配列で保持することなく算出する
- 両端から算出していくので正確なLeftMax, rightMaxがわからないが結局欲しいのはmin(LeftMax, rightMax)であるため問題ないという発想
- 低いBarが見つかった時点でそれ以上水の量は増えない


```java
public class Solution {
public int trap(int[] height) {
if (height == null || height.length == 0) {
return 0;
}

int l = 0, r = height.length - 1;
int leftMax = height[l], rightMax = height[r];
int res = 0;
while (l < r) {
if (leftMax < rightMax) {
l++;
leftMax = Math.max(leftMax, height[l]);
res += leftMax - height[l];
} else {
r--;
rightMax = Math.max(rightMax, height[r]);
res += rightMax - height[r];
}
}
return res;
}
}
```

## step3 3回とく
- step2のTwo Pointerで回答

```java
class Solution {
public int trap(int[] height) {
int left = 0;
int right = height.length - 1;
int leftMax = height[left];
int rightMax = height[right];
int ans = 0;
while (left < right) {
if (leftMax < rightMax) {
left++;
leftMax = Math.max(leftMax, height[left]);
ans += leftMax - height[left];
} else {
right--;
rightMax = Math.max(rightMax, height[right]);
ans += rightMax - height[right];
}
}
return ans;
}
}

```