1. [1,2,3,4,5] -> 3
  2. [1,2,3,4] -> 3 (後ろ側)
  3. [1] -> 1
  4. [1,2] -> 2
  5. [10,20,30] -> 20
  6. [1,2,3,4,5,6] -> 4
コース一覧
コンピューターサイエンス上級:アルゴリズムとデータ構造
リンクリストの中央ノード取得

コンピューターサイエンス上級:アルゴリズムとデータ構造

探索、ソート、木、グラフ、動的計画法、貪欲法など、競技プログラミングや技術面接で問われる高度なアルゴリズムとデータ構造を学べるコースです。基本的な CS の知識を持ち、アルゴリズム力を伸ばしたい学習者や、外資・大手の技術面接対策をしたい方を対象としています。約 13 時間 (1 日 30 分 × 26 日) で 50 レッスンを修了でき、修了後はコーディング面接の実装問題を構造的に解けるようになります。

1
連結リスト
01. リンクリスト構築と長さの計算5分
02. リンクリストの反転5分
03. リンクリストのサイクル検出5分
04. ソート済みリンクリストの merge5分
05. リンクリストの中央ノード取得5分
06. ソート済みリストの重複削除5分
07. 第1章まとめクイズ5分
2
二分木
01. 二分木の in-order 走査5分
02. 二分木の pre-order 走査5分
03. 二分木の post-order 走査5分
04. 二分木の幅優先走査 (BFS)5分
05. 二分木の高さ5分
06. 二分木の平衡判定5分
07. 第2章まとめクイズ — 二分木5分
3
探索木 (BST)
01. BST に値を挿入する5分
02. BST から値を検索する5分
03. BST の最小値と最大値5分
04. BST 妥当性チェック5分
05. BST で k 番目に小さい値5分
06. BST から値を削除する5分
07. 第 3 章 まとめクイズ5分
4
ハッシュとセット
01. hashmap で頻度集計5分
02. キーでグループ化5分
03. two sum (hash で O(n))5分
04. 部分配列の和 = k の個数5分
05. 最長連続部分列5分
06. 集合の積 (intersection)5分
07. 第4章まとめクイズ5分
5
グラフ
01. グラフ BFS で連結成分サイズを求める5分
02. グラフ DFS で連結成分の数を数える5分
03. グラフのパス存在判定5分
04. BFS で最短経路の長さを求める5分
05. トポロジカルソート5分
06. 2 部グラフ判定5分
07. ダイクストラ法 — 重み付きグラフの最短経路15分
08. 第5章まとめクイズ — グラフ5分
6
動的計画法 (上級)
01. 編集距離 (レーベンシュタイン距離)5分
02. 最長増加部分列(LIS)の解法 ── AOJ 2430 対応の動的計画法5分
03. 最大部分配列和 (Kadane)5分
04. 隣り合わない最大値 (House Robber)5分
05. グリッド経路数 (Unique Paths)5分
06. 単語分割可能か (Word Break)5分
07. 第6章まとめクイズ — 動的計画法 (上級)5分
7
総合データ構造と関数型
01. map と filter を組み合わせる5分
02. reduce で積を計算5分
03. 関数合成5分
04. カリー化5分
05. trie の単純検索 (prefix マッチ)5分
06. Union-Find (連結成分数)5分
07. 最終総まとめクイズ5分

リンクリストの中央ノード取得

前半と後半に分けたい、という場面はよくあります。そこで最初に要るのが、真ん中がどこかという情報です。ところが札をたどる形のリストでは、これが素直に取れません。

長さを数えてから、もう一度半分だけ歩く

配列なら要素数がその場で分かるので迷いません。ところが札をたどる形のリストには、長さを聞ける相手がいません。数えるしかありません。

Python

n = 0 cur = head while cur is not None: n += 1 cur = cur.next cur = head for _ in range(n // 2): cur = cur.next

答えは合っています。ただ、同じ道を 2 回歩いています。しかも 1 周目が終わるまで、真ん中がどこかは 1 ミリも分かりません。長さが分からないまま真ん中に着く方法はないものか、という話になります。

2 周する書き方が悪いわけではありません。件数が少なければ差は出ませんし、読みやすさはむしろ上です。ただ「数えてから戻る」しか手が無いと、長さを聞けない相手を渡されたときに思考が止まります。

2 倍の速さで歩くほうが端に着いたとき

サイクル検出で使った 2 つの目印を、そのまま持ってきます。片方は 1 歩、もう片方は 2 歩です。

Python

slow = head fast = head while fast is not None and fast.next is not None: slow = slow.next fast = fast.next.next

速いほうが k 回進んだとき、進んだ距離は 2k です。それが端に届いたということは、2k がほぼ全長ということです。すると遅いほうがいる k は全長のおよそ半分になります。歩き終わった瞬間、slow が真ん中に立っています。1 周で済みました。

止める条件で確かめているのは、2 歩ぶんの余地があるかどうかです。1 歩ぶんしか見ずに 2 つ動かすと、末尾の先へはみ出します。ノードなら空に next を聞いて落ち、番号で持つなら範囲外を読みます。境界の確認を 2 つ分書く必要があるのは、そのためです。

真ん中が 2 つあるとき、どちらを返すか

長さが奇数なら真ん中は 1 つに決まります。偶数のときは 2 つあり、どちらになるかは止め方で変わります。

長さ進んだ回数slow がいる位置
523 番目
423 番目
212 番目
101 番目

今回の課題は、偶数のとき後ろ側を返す決まりです。[1, 2, 3, 4] なら 3 になります。前側が欲しい仕様のときは、止める判定を 1 つ手前に置きます。仕様として先に決めておかないと、テストが偶数長のときだけ落ちて、原因が見えにくくなります。

真ん中が要る場面を具体的に見ておきます。並べ替えのために 2 つに割るとき、割る位置がずれると片方だけが長くなり、段数が増えて遅くなります。回文かどうかを調べるときは、前半と後半の長さがそろっていないと比較そのものが噛み合いません。真ん中を正確に取れることが、その先の処理の前提になっています。

なお長さが 1 のときは、1 度も進まずに先頭がそのまま答えです。書いた条件がこの場合に 1 回でも回らないか、手で確かめておいてください。

要件

  1. 連結リストは配列 arr (長さ 1 以上) で表現する
  2. slow / fast 2 ポインタ法を使って 1 パスで取得すること
  3. 偶数長のときは後ろ側の中央を返す (例: [1,2,3,4] -> 3)

入出力例

middleNode([1,2,3,4,5]) → 3 middleNode([1,2,3,4]) → 3 middleNode([1]) → 1 middleNode([1,2]) → 2 middleNode([10,20,30]) → 20 middleNode([1,2,3,4,5,6]) → 4

ヒント

slow = 0, fast = 0 から始め、while で slow を 1 歩、fast を 2 歩ずつ進める

fast + 1 < len(arr) の条件で範囲外を防ぐ

fast が末尾に達したとき、slow が中央を指している

生田 陸人
監修生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア監修者プロフィールを見る →
編集 ゆめさく編集部·公開 2026/05/19·更新 2026/08/26

関連レッスン

  • ソート済みリストの重複削除

    ソート済み連結リストから連続する重複ノードを除去し、in-place な編集の発想を身につける。

  • 第1章まとめクイズ

    連結リストの基本操作・サイクル検出・2 ポインタ法の理解度を確認するまとめクイズ。

  • 二分木の in-order 走査

    二分木を配列表現で受け取り、in-order (左 → 根 → 右) で訪問した値の配列を返す関数を実装する。

  • BST に値を挿入する

    二分探索木 (BST) に新しい値を挿入し、挿入後の in-order 走査結果を配列で返す関数を実装する。

このレッスンに出てくる用語

意味があいまいなまま進んだ語は、ここから読み直せます。

  • リスト順序付きで複数の値を扱うデータ構造
  • 配列サイズ固定の同型データの集まり
  • 素数1 と自分自身でしか割り切れない自然数
  • テストバグを見つける工程
  • 処理計算や代入を表す長方形
  • 連結リスト各要素が次の要素へのポインタを持つ構造。
main.py
学習モード
エディタを読み込んでいます

メモ

リンクリストの中央ノード取得

⌘S で保存