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
14 changes: 14 additions & 0 deletions 11.ContainerWithMostWater/brute_force.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class Solution {
public:
int maxArea(vector<int>& heights) {
int max_amount_water = -1;
for (int i = 0; i < heights.size(); i++) {
for (int j = 0; j < heights.size(); j++) {
int width = j - i;
int height = min(heights[i], heights[j]);
max_amount_water = max(max_amount_water, height * width);
}
}
return max_amount_water;
}
};
34 changes: 34 additions & 0 deletions 11.ContainerWithMostWater/memo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
## ステップ1
まず思いついたのはブルートフォースを使った解法
2つのループを使って各区間の高さと幅を求めて水の量が最大になるか確認する
時間計算量はO(n^2)で入力データ数は10^5なので10^10となりC++でも1秒内に処理できない
brute_force.cppに実装。Leetcode上ではTLE


全ての区間を確認するのではなく、2つのポインターを用いて両サイドから幅を狭めつつ水の量を確認する
水量 = min(左側の高さ, 右側の高さ) × (右側のインデックス - 左側のインデックス)
左右両端のインデックスえを最初に選ぶと、幅は最も広い状態になる
低い方を動かす場合、幅は狭まるものの高さが上がる可能性があり、その場合には水量が増える
高い方を動かす場合、幅は狭まり高さは維持もしくは低くなる可能性がある

低い方を狭まる方針をleftとrightがぶつかるまで行う
時間計算量O(n)
空間計算量O(1)
acceptまで7分

## ステップ2
そもそもheightsがからの場合0を返却する処理を追加
max_amount_waterの初期値を-1から0へ変更

## ステップ3
**3回書き直しやりましょう、といっているのは、不自然なところや負荷の高いところは覚えられないからです。**

## 他の解法
Segment Treeで解く方法も存在する
そもそも名前しか知らないので調べるところから始めます。
https://github.com/thonda28/leetcode/pull/16

2ポインターの解法がなぜうまくいくのか説明するのは難しい気がする
https://github.com/Jikuhara/LeetCode/pull/8
## Discorなど

19 changes: 19 additions & 0 deletions 11.ContainerWithMostWater/step1.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
class Solution {
public:
int maxArea(vector<int>& heights) {
int left = 0;
int right = heights.size() - 1;
int max_amount_water = -1;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

memo に書いてましたが、-1 での初期化は違和感がありました。0 がよいと思います

while (left < right) {
int height = min(heights[left], heights[right]);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

先に left または right を動かしてから、 max_amount_water を更新してもよいと思いました。ループの前に max_amount_water を、両端を壁にしたときの水の容量で初期化しておく必要はあります。

int width = right - left;
max_amount_water = max(max_amount_water, height * width);
if (heights[left] < heights[right]) {
left++;
} else {
right--;
}
}
return max_amount_water;
}
};
23 changes: 23 additions & 0 deletions 11.ContainerWithMostWater/step2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
class Solution {
public:
int maxArea(vector<int>& heights) {
if (heights.empty()) {
return 0;
}
Comment on lines +4 to +6
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

この部分がなくても heights が empty のときには 0 を返すように思いました。(while 文を通らないので初期値の 0 をそのまま返す)
そのまま処理しても問題がない場合は特殊処理を追加せず、うまく動かないケースのみをエッジケースとして特殊処理で弾くのがよいのではと個人的には思います。


int left = 0;
int right = heights.size() - 1;
int max_amount_water = 0;
while (left < right) {
int height = min(heights[left], heights[right]);
int width = right - left;
max_amount_water = max(max_amount_water, height * width);
if (heights[left] < heights[right]) {
left++;
} else {
right--;
}
}
return max_amount_water;
}
};
22 changes: 22 additions & 0 deletions 11.ContainerWithMostWater/step3.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
class Solution {
public:
int maxArea(vector<int>& heights) {
if (heights.empty()) {
return 0;
}
int left = 0;
int right = heights.size() - 1;
int max_amount_water = 0;
while (left < right) {
int height = min(heights[left], heights[right]);
int width = right - left;
max_amount_water = max(max_amount_water, height * width);
if (heights[left] < heights[right]) {
left++;
} else {
right--;
}
}
return max_amount_water;
}
};