Skip to content

Commit a4bec55

Browse files
committed
leetcode 11. Container With Most Water two pointers
1 parent 0d6f67a commit a4bec55

3 files changed

Lines changed: 313 additions & 0 deletions

File tree

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# LeetCode では、**クラスベースの構造(`class Solution:`)が要求される仕様**です。
2+
# あなたのエラー:
3+
4+
# ```
5+
# NameError: name 'Solution' is not defined
6+
# ```
7+
8+
# は、LeetCode のドライバコードが `Solution().maxArea(...)` を呼び出そうとしているため、`Solution` クラスがないと怒られているという状況です。
9+
10+
# ---
11+
12+
# ## ✅ LeetCode 用に修正した Python 解答
13+
14+
# ```python
15+
from typing import List
16+
17+
class Solution:
18+
def maxArea(self, height: List[int]) -> int:
19+
left: int = 0
20+
right: int = len(height) - 1
21+
max_area: int = 0
22+
23+
while left < right:
24+
h: int = min(height[left], height[right])
25+
w: int = right - left
26+
area: int = h * w
27+
max_area = max(max_area, area)
28+
29+
if height[left] < height[right]:
30+
left += 1
31+
else:
32+
right -= 1
33+
34+
return max_area
35+
# ```
36+
37+
# ---
38+
39+
# ## ✅ 使い方(LeetCodeでは不要だがローカルテスト用)
40+
41+
# ```python
42+
# # LeetCodeでは以下は必要ありません。自動で呼ばれます。
43+
# if __name__ == "__main__":
44+
# s = Solution()
45+
# print(s.maxArea([1,8,6,2,5,4,8,3,7])) # 出力: 49
46+
# ```
47+
48+
# ---
49+
50+
# ## 🧠 メモ
51+
52+
# | 特徴 | 内容 |
53+
# | ---------- | -------------------- |
54+
# | 型ヒント | `List[int] -> int` |
55+
# | 時間計算量 | O(n) |
56+
# | 空間計算量 | O(1)(ポインタと変数のみ) |
57+
# | LeetCode対応 | `class Solution` が必須 |
58+
59+
# ---
60+
61+
# これで `Solution` エラーは解消され、LeetCode に貼り付けて提出すれば問題なく動作します。
62+
63+
# ---
64+
65+
# ## 🧠 時間・空間計算量
66+
67+
# | 指標 | 値 | 説明 |
68+
# | --------- | ------ | --------------- |
69+
# | **時間計算量** | `O(n)` | 配列を一度走査するだけ |
70+
# | **空間計算量** | `O(1)` | 追加の配列や辞書などは使わない |
71+
72+
# ---
73+
74+
# ## 📈 LeetCode 上の性能(目安)
75+
76+
# (2025年現在のLeetCode Python環境での参考値)
77+
78+
# * **実行時間**: 約 **500–800ms**(入力サイズによる)
79+
# * **メモリ使用量**: 約 **27–30MB**
80+
# * CPython 3.11.4 環境でもこのアルゴリズムは**線形時間で高速に処理可能**
81+
82+
# ---
83+
84+
# ## 🔍 補足: なぜ Two Pointers が効率的か?
85+
86+
# * すべての組み合わせを調べると **O(n²)** になって非効率。
87+
# * 一方で、両端から内側に向かって探索することで、**必要な組み合わせだけを調べられる**。
88+
# * 常に「**幅が広い状態で高さの低い方を捨てる**」ことで面積を最大化できる戦略です。
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// 以下は、LeetCode 11「Container With Most Water」のTypeScriptでの効率的な解法です。処理時間とメモリ使用量を意識し、**O(n)** 時間・**O(1)** 空間のアルゴリズム(ツーポインター法)を用いています。
2+
3+
// ---
4+
5+
// ### ✅ **TypeScript 解法(Two Pointers アプローチ)**
6+
7+
// ```ts
8+
function maxArea(height: number[]): number {
9+
let maxArea = 0;
10+
let left = 0;
11+
let right = height.length - 1;
12+
13+
while (left < right) {
14+
const h = Math.min(height[left], height[right]);
15+
const w = right - left;
16+
const area = h * w;
17+
maxArea = Math.max(maxArea, area);
18+
19+
// 高さの小さい方を内側に移動する
20+
if (height[left] < height[right]) {
21+
left++;
22+
} else {
23+
right--;
24+
}
25+
}
26+
27+
return maxArea;
28+
}
29+
30+
// ### 🔍 **アルゴリズムの概要**
31+
32+
// * **初期化**: 両端(`left=0`, `right=n-1`)からスタート
33+
// * **ループ処理**:
34+
35+
// * 面積 = `min(height[left], height[right]) * (right - left)`
36+
// * 最大面積を更新
37+
// * より**低い方のポインタ**を内側に動かす(より高い線が存在する可能性があるため)
38+
39+
// ---
40+
41+
// ### 🧠 **時間・空間計算量**
42+
43+
// | 項目 | 値 |
44+
// | ----- | ------------ |
45+
// | 時間計算量 | O(n) |
46+
// | 空間計算量 | O(1)(追加領域なし) |
47+
48+
// ---
49+
50+
// ### ✅ **テスト例**
51+
52+
// ```ts
53+
// console.log(maxArea([1,8,6,2,5,4,8,3,7])); // 49
54+
// console.log(maxArea([1,1])); // 1
55+
// console.log(maxArea([4,3,2,1,4])); // 16
56+
// console.log(maxArea([1,2,1])); // 2
57+
// ```
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
はい、`maxArea` アルゴリズム(ツーポインター法)を **図解付きで各ステップを具体的に説明** します。以下では、例として `height = [1,8,6,2,5,4,8,3,7]` を使って解説します。
2+
3+
---
4+
5+
## 🏗️ 問題の可視化
6+
7+
`height = [1,8,6,2,5,4,8,3,7]`
8+
この配列は、以下のような棒グラフと見なせます(x軸: index、y軸: height):
9+
10+
```
11+
↑ y
12+
10|
13+
9|
14+
8| █ █
15+
7| █ █
16+
6| █
17+
5| █
18+
4| █
19+
3| █
20+
2| █
21+
1|█ █
22+
+-------------------------
23+
0 1 2 3 4 5 6 7 8 → x (index)
24+
```
25+
26+
---
27+
28+
## 🎯 アルゴリズムの目的
29+
30+
* **x軸と2つの縦線**で囲まれる「水を入れる容器」の面積(=`幅 × 高さ`)を最大化します。
31+
* 斜めはダメ。両端を固定して面積を計算し、**どちらかのポインタを内側に移動**させます。
32+
33+
---
34+
35+
## 🧮 処理ステップの図解
36+
37+
### ✅ Step 1:
38+
39+
* `left = 0`, `right = 8`(端からスタート)
40+
* 高さ: `min(height[0], height[8]) = min(1, 7) = 1`
41+
* 幅: `8 - 0 = 8`
42+
* 面積: `1 × 8 = 8`
43+
44+
```
45+
46+
7| █ █ ← height[8]=7
47+
1|█ █ ← height[0]=1
48+
↑ ↑
49+
left(0) right(8)
50+
```
51+
52+
👉 左が低いので `left++`(内側へ)
53+
54+
---
55+
56+
### ✅ Step 2:
57+
58+
* `left = 1`, `right = 8`
59+
* 高さ: `min(8, 7) = 7`
60+
* 幅: `7`
61+
* 面積: `7 × 7 = 49` ✅ 最大更新!
62+
63+
```
64+
8| █ █
65+
7| █ █
66+
↑ ↑
67+
left(1) right(8)
68+
```
69+
70+
👉 右が低いので `right--`
71+
72+
---
73+
74+
### ✅ Step 3:
75+
76+
* `left = 1`, `right = 7`
77+
* 高さ: `min(8, 3) = 3`
78+
* 幅: `6`
79+
* 面積: `3 × 6 = 18`
80+
81+
```
82+
8| █
83+
3| █
84+
↑ ↑
85+
left(1) right(7)
86+
```
87+
88+
👉 右が低いので `right--`
89+
90+
---
91+
92+
### ✅ Step 4:
93+
94+
* `left = 1`, `right = 6`
95+
* 高さ: `min(8, 8) = 8`
96+
* 幅: `5`
97+
* 面積: `8 × 5 = 40`
98+
99+
```
100+
8| █ █
101+
↑ ↑
102+
left(1) right(6)
103+
```
104+
105+
👉 左右同じなので `right--`(どちらでもOK)
106+
107+
---
108+
109+
### ✅ Step 5:
110+
111+
* `left = 1`, `right = 5`
112+
* 高さ: `min(8, 4) = 4`
113+
* 幅: `4`
114+
* 面積: `4 × 4 = 16`
115+
116+
👉 `right--`
117+
118+
---
119+
120+
### ✅ Step 6:
121+
122+
* `left = 1`, `right = 4`
123+
* 高さ: `min(8, 5) = 5`
124+
* 幅: `3`
125+
* 面積: `5 × 3 = 15`
126+
127+
👉 `right--`
128+
129+
---
130+
131+
### ✅ Step 7:
132+
133+
* `left = 1`, `right = 3`
134+
* 高さ: `min(8, 2) = 2`
135+
* 幅: `2`
136+
* 面積: `2 × 2 = 4`
137+
138+
👉 `right--`
139+
140+
---
141+
142+
### ✅ Step 8:
143+
144+
* `left = 1`, `right = 2`
145+
* 高さ: `min(8, 6) = 6`
146+
* 幅: `1`
147+
* 面積: `6 × 1 = 6`
148+
149+
👉 `right--` → 終了(`left == right`
150+
151+
---
152+
153+
## ✅ 結果
154+
155+
最大面積 = **49**
156+
157+
---
158+
159+
## 🧠 ポイントまとめ
160+
161+
| ステップ | 処理 |
162+
| ------ | --------------------------------------------------- |
163+
| 初期化 | `left=0, right=n-1` |
164+
| 面積計算 | `(right - left) * min(height[left], height[right])` |
165+
| ポインタ更新 | 小さい方を内側へ動かす(→ 高さの可能性を探す) |
166+
| 終了条件 | `left >= right` |
167+
168+
---

0 commit comments

Comments
 (0)