1. [1,3,5] と [2,4,6] -> [1,2,3,4,5,6]
  2. [1,2,3] と [4,5,6] -> [1,2,3,4,5,6]
  3. [1] と [2] -> [1,2]
  4. [1,1,1] と [1,1] -> [1,1,1,1,1]
  5. [5,10] と [1,2,3] -> [1,2,3,5,10]
コース一覧
コンピューターサイエンス上級:アルゴリズムとデータ構造
ソート済みリンクリストの merge

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

探索、ソート、木、グラフ、動的計画法、貪欲法など、競技プログラミングや技術面接で問われる高度なアルゴリズムとデータ構造を学べるコースです。基本的な 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分

ソート済みリンクリストの merge

2 台のサーバーが、それぞれ時刻順にログを吐いています。どちらの中身もきれいに並んでいます。この 2 本を、時刻順のまま 1 本にまとめたい、という話です。

残り全部から一番古いものを探すのは、もったいない

素直にやるなら、まだ取っていないログを全部見比べて一番古いものを選ぶ、を繰り返すことになります。1 件選ぶたびに残り全部を見るので、件数が増えると急に重くなります。

けれど、両方すでに時刻順です。ということは、まだ取っていない中で一番古いログは、必ずどちらかの先頭にあります。奥のほうを見る意味はありません。見比べるのは、いつでも 2 件だけで足ります。

先頭 2 件を比べて、取ったほうだけ進める

それぞれのログに、どこまで読んだかを覚えておく位置を 1 つずつ持たせます。

Python

if logA[pa] <= logB[pb]: taken = logA[pa] pa += 1 else: taken = logB[pb] pb += 1

JavaScript でも同じです。

JavaScript

if (logA[pa] <= logB[pb]) { taken = logA[pa]; pa++; } else { taken = logB[pb]; pb++; }

取ったほうの位置だけを進めるのが要です。両方進めてしまうと、選ばれなかった側の 1 件が誰にも見られないまま置き去りになります。

[1, 3, 5] と [2, 4, 6] を並べたときの動きは次のとおりです。

見ている 2 件取るのは次に見る 2 件
1 と 213 と 2
3 と 223 と 4
3 と 435 と 4
5 と 445 と 6
5 と 65空 と 6

同じ時刻が両方にあったとき、<= なら logA の側が先に出ます。< にすると逆になります。どちらでも並びは時刻順ですが、同着の扱いが変わるので、比較の向きは意識して決めてください。

片方が先に尽きる

表の最終行で logA の側が末尾を越えました。ここで比較を続けようとすると、存在しない場所を読むことになります。比べるのは「両方にまだ残っている間」だけです。

抜けたあとには、片方の残りがそのまま残っています。この残りは、すでに時刻順に並んでいて、しかも取り出し済みのどれよりも新しい。並べ替えは 1 回も要りません。そのままの順で後ろへ足せば終わりです。ここを忘れると結果が短くなり、しかも件数が合わないだけで並びは正しいので、原因に気づくまで時間がかかります。

片方が最初から空のときも、同じ理屈で片付きます。比較のループは 1 度も回らず、もう片方がまるごと残りとして出ていきます。特別扱いの分岐を書き足す必要はありません。

この「先頭 2 件だけ見る」は、分割して統合する並べ替えの後半そのものです。半分ずつに割ってそれぞれ並べ、最後にこの手順で 1 本へ戻します。全体が速く終わるのは、統合の 1 回が全件を 1 度なぞるだけで済むからです。

札でつないだリストが相手なら、新しい入れ物すら要りません。取ると決めたノードの札を、結果の末尾から張り替えていくだけです。値のコピーが 1 回も起きないので、1 件あたりが大きいデータほど差が出ます。

要件

  1. 両方の配列は昇順ソート済みであると仮定して良い
  2. 2 ポインタ法で O(n + m) で実装すること
  3. 戻り値は昇順ソートされた新しい配列

入出力例

mergeSortedLists([1,3,5], [2,4,6]) → [1,2,3,4,5,6] mergeSortedLists([1,2,3], [4,5,6]) → [1,2,3,4,5,6] mergeSortedLists([1], [2]) → [1,2] mergeSortedLists([1,1,1], [1,1]) → [1,1,1,1,1] mergeSortedLists([5,10], [1,2,3]) → [1,2,3,5,10]

ヒント

2 つのインデックス i, j を 0 から始め、小さい方を result に追加して該当インデックスを進める

メインの while を抜けた後、片方の残りを result に追加するループを 2 つ書く

arr1.concat(arr2).sort() でも答えは合うが、O(n+m) ではなく O((n+m) log(n+m)) になる

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

関連レッスン

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

    slow / fast の 2 ポインタ法を使って連結リストの中央ノードの値を一発で取得する。

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

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

  • 第1章まとめクイズ

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

  • 二分木の in-order 走査

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

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

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

  • サーバークライアント(ブラウザなど)がリクエストを送り、サーバーがレスポンスを返す。
  • JavaScriptWeb で動的な振る舞いを担う言語
  • ループ繰り返し処理。矢印で戻すか専用記号で示す
  • リスト順序付きで複数の値を扱うデータ構造
  • 配列サイズ固定の同型データの集まり
  • 戻り値呼び出し元への返答を表す点線矢印
main.py
学習モード
エディタを読み込んでいます

メモ

ソート済みリンクリストの merge

⌘S で保存