つなぎ先の 付け替えで 連結リストを k 個ずつ逆順にする
連結リストを
海外で定番の問題リスト 4 本には入っていません
問題
連結リストのhead とk をk 個ずつの
- 最後に
k個に足りない 節が 残ったら、 その 残りは 元の 順のままにします - 節の
値を 書き換えず、 節の つなぎ先を 付け替えてください - 各節は
val(値) とnext(次の節) を 持ちます。 最後の 節の nextは、Python では None、JavaScript では null、Go では nilです。Go の 節は ListNodeで、Val、Nextと大文字で 始まります - 節の
数は 1 以上 5000 以下、 kは 1 以上、節の 数以下です。 値は どれも 0 以上 1000 以下です - 追加の
記憶は O(1) に してください
例では、
入力と出力の例
例 1
3
例 2
2
例 3
k が 1 なら、
面接での聞かれ方
連結リストの
- 「連結リストを k 個ずつ逆に
してください。 足りない 残りは そのままです」 - 連結リストを
逆に する 問題 (この 一覧の reverse-linked-list) を 書いた あとの 続きとして 出される ことが よくあります - 再帰で
書くと 短くなりますが、 「追加の 記憶を O(1) に できますか?」と 繰り返しの 書き方を 求められる ことがあります
シニアの
ヒント
まだ開いていません
付箋は 4 枚。下の段ほど答えに近づきます
ヒント 2
ヒント 3
ヒント 4答えに近い
アルゴリズムのチートシートの「配列と文字列」に、
関わる学び
配列と
まず 考える手順
段 1
まずは
段 2
組ごとにprev から k 歩先まで
段 3
組の k 個をprev の
段 4
元のprev にdummy をprev にし、dummy.next を
解答
Python
Python
def reverse_k_group(head, k):
dummy = ListNode(0, head)
prev = dummy
while True:
end = prev
for _ in range(k):
end = end.next
if not end:
break
if not end:
return dummy.next
nxt = end.next
first = prev.next
cur, back = first, nxt
while cur is not nxt:
after = cur.next
cur.next = back
back = cur
cur = after
prev.next = end
prev = firstJavaScript
JavaScript
function reverseKGroup(
head, k
) {
const dummy = new ListNode(
0, head
);
let prev = dummy;
while (true) {
let end = prev;
let left = k;
while (left > 0) {
end = end.next;
if (end === null) {
return dummy.next;
}
left--;
}
const nxt = end.next;
const first = prev.next;
let cur = first;
let back = nxt;
while (cur !== nxt) {
const after = cur.next;
cur.next = back;
back = cur;
cur = after;
}
prev.next = end;
prev = first;
}
}Go
Go
func reverseKGroup(
head *ListNode, k int,
) *ListNode {
dummy := &ListNode{Next: head}
prev := dummy
for {
end := prev
for i := 0; i < k; i++ {
end = end.Next
if end == nil {
return dummy.Next
}
}
nxt := end.Next
first := prev.Next
cur, back := first, nxt
for cur != nxt {
after := cur.Next
cur.Next = back
back = cur
cur = after
}
prev.Next = end
prev = first
}
}end はnxt はfirst はend がfirst が
計算量
- 時間は O(n) です。
どの 節も、 k 個そろっているかを 確かめる 所で 1 回、 逆に する 所で 1 回、 合わせて 2 回ずつ通るだけです - 使う
記憶は O(1) です。 ダミーの 節 1 つと 指を 何本か 持つだけです
よく ある間違い
- 足りない
残りまで 逆にする。 k 個そろっているかを 確かめずに 逆に すると、 例 1 の 7、 8 が 8、 7 に なります。 逆に する 前に k 歩先まで数えます - 組の
最後を 次の 組に つなぎ忘れる。 逆に する ときの 最初の つなぎ先を 空に すると、 組の 元の 先頭が 空を 指し、 次の 組から 先が 切れます。 backを次の 組の 先頭 nxtから始めます prevを進め忘れる、 または endに進める。 次の組の 1 つ前は、 逆に した あとの 組の 最後、 つまり元の 先頭の firstです。endに進めると、 同じ組を また 逆にします - 先頭の
組だけ別に書く。 先頭の 組は 「1 つ前の節」が 無いので 場合分けしたくなりますが、 ダミーを 置けばどの 組も 同じ 書き方で済みます
解答を動かした版 Python 3.14.7Node.js 24.22.1Go 1.24.2確認日 2026年11月8日
面接での 話し方の例
書き始める
「組の 1 つ前の
節 prev から k 歩進めて、 k 個そろっているかを 確かめます。 そろっていれば、 組の 中を 逆にしますが、 最初の つなぎ先を 次の 組の 先頭に しておくと、 逆に し終えた 時点で 後ろと つながっています。 prev の 次を 組の 新しい 先頭に 付け替え、 元の 先頭を 次の prev にします。 そろわなければ 終わりです。 時間は O(n)、 記憶は O(1) です。」
書き終えたら、
「例 1 で k は 3 です。
ダミーから 3 歩で 3 に 着くので、 1、 2、 3 を 逆にし、 1 の 次は 4 です。 ダミーの 次を 3 に して、 prev を 1 に 進めます。 1 から 3 歩で 6 に 着くので 4、 5、 6 を 逆にし、 4 の 次は 7、 1 の 次を 6 にします。 prev を 4 に して 3 歩進めると、 7、 8 の あとが 空なので 終わり、 3、 2、 1、 6、 5、 4、 7、 8 です。」