Skip to content

Commit 4dad49f

Browse files
committed
leetcode 25. Reverse Nodes in k-Group singly-linked list
1 parent 784fac2 commit 4dad49f

7 files changed

Lines changed: 1133 additions & 0 deletions

File tree

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
以下に、「連結リストを k 個ずつ反転する」問題において、各処理ステップを **図解とともに** 詳しく解説します。Python 実装に基づいて、`k = 3` の例 `head = [1 → 2 → 3 → 4 → 5 → 6 → 7]` を使います。
2+
3+
---
4+
5+
## ✅ 初期構造と目的
6+
7+
```
8+
Input List: 1 → 2 → 3 → 4 → 5 → 6 → 7
9+
k = 3
10+
11+
目標:
12+
1グループ目 → [1,2,3] → 反転 → 3 → 2 → 1
13+
2グループ目 → [4,5,6] → 反転 → 6 → 5 → 4
14+
残り → [7] はk未満なのでそのまま
15+
16+
出力: 3 → 2 → 1 → 6 → 5 → 4 → 7
17+
```
18+
19+
---
20+
21+
## ✅ ステップ別処理図解
22+
23+
### 🔷 Step 1: 長さのカウント
24+
25+
```python
26+
node = head
27+
while node:
28+
count += 1
29+
node = node.next
30+
```
31+
32+
```
33+
1 → 2 → 3 → 4 → 5 → 6 → 7
34+
↑ ↑ ↑ ↑ ↑ ↑
35+
1 2 3 4 5 6 7ノードあるので count = 7
36+
```
37+
38+
---
39+
40+
### 🔷 Step 2: ダミーノード作成
41+
42+
```python
43+
dummy = ListNode(0)
44+
dummy.next = head
45+
prev_group_end = dummy
46+
```
47+
48+
```
49+
dummy → 1 → 2 → 3 → 4 → 5 → 6 → 7
50+
51+
prev_group_end
52+
```
53+
54+
ダミーノードにより、最初のグループの先頭を簡単に付け替え可能。
55+
56+
---
57+
58+
### 🔷 Step 3: 最初の3ノードを反転(1回目)
59+
60+
```python
61+
prev = None
62+
curr = prev_group_end.next # 1
63+
group_start = curr # 1
64+
65+
for _ in range(k):
66+
next_node = curr.next
67+
curr.next = prev
68+
prev = curr
69+
curr = next_node
70+
```
71+
72+
#### ⏳反転処理の流れ
73+
74+
```
75+
初期:
76+
prev = None
77+
curr = 1 → 2 → 3
78+
79+
1回目:
80+
curr = 1 → 2
81+
1.next → None(prev)
82+
prev = 1
83+
84+
2回目:
85+
curr = 2 → 3
86+
2.next → 1
87+
prev = 2 → 1
88+
89+
3回目:
90+
curr = 3 → 4
91+
3.next → 2 → 1
92+
prev = 3 → 2 → 1
93+
```
94+
95+
結果: `prev = 3 → 2 → 1`, `curr = 4`
96+
97+
---
98+
99+
### 🔷 Step 4: 接続調整(グループ外リンク修正)
100+
101+
```python
102+
prev_group_end.next = prev # dummy.next = 3
103+
group_start.next = curr # 1.next = 4
104+
prev_group_end = group_start
105+
```
106+
107+
```
108+
dummy → 3 → 2 → 1 → 4 → 5 → 6 → 7
109+
110+
prev_group_end
111+
```
112+
113+
---
114+
115+
### 🔷 Step 5: 次の3ノードを反転(2回目)
116+
117+
反転対象: 4 → 5 → 6
118+
初期状態:
119+
120+
```
121+
prev = None
122+
curr = 4
123+
group_start = 4
124+
```
125+
126+
#### ⏳反転処理
127+
128+
```
129+
1回目: 4.next → None(prev) → prev = 4
130+
2回目: 5.next → 4 → prev = 5 → 4
131+
3回目: 6.next → 5 → 4 → prev = 6 → 5 → 4
132+
```
133+
134+
curr = 7
135+
136+
---
137+
138+
### 🔷 Step 6: 接続調整(再び)
139+
140+
```python
141+
prev_group_end.next = prev # 1.next = 6
142+
group_start.next = curr # 4.next = 7
143+
prev_group_end = group_start # prev_group_end = 4
144+
```
145+
146+
結果:
147+
148+
```
149+
dummy → 3 → 2 → 1 → 6 → 5 → 4 → 7
150+
151+
prev_group_end
152+
```
153+
154+
---
155+
156+
### 🔷 Step 7: 残りノード < k(終了)
157+
158+
* 残りノード数 = 1(7のみ)
159+
* `count = 1 < k` なのでループ終了
160+
161+
---
162+
163+
## ✅ 最終結果
164+
165+
```
166+
出力:
167+
3 → 2 → 1 → 6 → 5 → 4 → 7
168+
```
169+
170+
---
171+
172+
## ✅ 全体処理フローまとめ図(抽象)
173+
174+
```
175+
dummy → [kノード] → [kノード] → 残りノード
176+
↓反転 ↓反転 そのまま
177+
178+
dummy → reversed_k1 → reversed_k2 → rest
179+
```
180+
181+
---
182+
183+
## ✅ 時間・空間複雑度(再確認)
184+
185+
| 指標 ||
186+
| ----- | -------------------- |
187+
| 時間計算量 | O(n)(各ノードを一度ずつ操作) |
188+
| 空間計算量 | O(1)(追加ノードなし) |
189+
| メモリ | リスト構造のみ使用 |
190+
| 実行時間 | ≒ 80〜100ms(LeetCode) |
191+
192+
---
193+
194+
図付きステップやアニメーション的な表示をご希望であれば、さらに細かくビジュアルで表現することも可能です。ご希望があれば教えてください。
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// 以下に、**LeetCode環境(Node.js 18.16.1)向け**に「k個ずつノードを反転する」問題の解法を、**関数形式で記述したJavaScriptコード**を提示します。
2+
// **ノードの値は変更せず、ノード自体を操作する必要があります。**
3+
4+
// ---
5+
6+
// ## ✅ 実装の概要
7+
8+
// * `reverseKGroup` 関数を定義。
9+
// * ノードをk個ずつ確認して反転。
10+
// * 反転できない残りのノードはそのまま保持。
11+
// * O(1) 空間(再帰なし・配列使用なし)で対応。
12+
13+
// ---
14+
15+
// ### ✅ JavaScript 実装(関数形式)
16+
17+
// ```javascript
18+
/**
19+
* Definition for singly-linked list.
20+
* function ListNode(val, next) {
21+
* this.val = (val===undefined ? 0 : val);
22+
* this.next = (next===undefined ? null : next);
23+
* }
24+
*/
25+
26+
/**
27+
* @param {ListNode} head - 単方向連結リストの先頭ノード
28+
* @param {number} k - グループ単位の反転サイズ(1 <= k <= n)
29+
* @return {ListNode} - k個ごとに反転された新しいリストの先頭ノード
30+
*/
31+
function reverseKGroupJs(head, k) {
32+
if (k === 1 || head === null) return head;
33+
34+
// 長さを測定
35+
let count = 0;
36+
let node = head;
37+
while (node !== null) {
38+
count++;
39+
node = node.next;
40+
}
41+
42+
// ダミーヘッド(操作の単純化)
43+
let dummy = new ListNode(0);
44+
dummy.next = head;
45+
46+
let prevGroupEnd = dummy;
47+
48+
while (count >= k) {
49+
let prev = null;
50+
let curr = prevGroupEnd.next;
51+
let next = null;
52+
let groupStart = curr;
53+
54+
// k個反転
55+
for (let i = 0; i < k; i++) {
56+
next = curr.next;
57+
curr.next = prev;
58+
prev = curr;
59+
curr = next;
60+
}
61+
62+
// 接続処理
63+
prevGroupEnd.next = prev;
64+
groupStart.next = curr;
65+
prevGroupEnd = groupStart;
66+
count -= k;
67+
}
68+
69+
return dummy.next;
70+
}
71+
72+
// ## ✅ 処理の流れ(図解付き)
73+
74+
// ### 例: `head = [1, 2, 3, 4, 5], k = 3`
75+
76+
// 1. `1 → 2 → 3 → 4 → 5`
77+
// 2. `3 → 2 → 1 → 4 → 5`(最初の3つを反転)
78+
// 3. 残り(4,5)は反転されずそのまま
79+
80+
// ---
81+
82+
// ## ✅ 時間・空間計算量
83+
84+
// | 項目 | 値 |
85+
// | ------ | -------------------- |
86+
// | 時間計算量 | O(n) |
87+
// | 空間計算量 | O(1)(再帰なし、定数領域) |
88+
// | メモリ消費 | ノード再配置のみ |
89+
// | 実行速度目安 | 約100ms前後(LeetCode基準) |
90+
91+
// ---
92+
93+
// ## ✅ 補足
94+
95+
// * `ListNode` は LeetCode が自動的に用意するので、自分で定義しなくてOK。
96+
// * クラスベースでなく、関数形式にしたため他コードとの結合も簡単です。
97+
98+
// ---
99+
100+
// 必要であれば、テスト用コードや図でのステップ解説も追記可能です。

0 commit comments

Comments
 (0)