1. gcd(12, 18) = 6
  2. gcd(18, 12) = 6 (引数の順入れ替え)
  3. gcd(7, 13) = 1 (互いに素)
  4. gcd(100, 25) = 25 (片方が倍数)
  5. gcd(48, 36) = 12
  6. gcd(1, 1) = 1
コース一覧
コンピューターサイエンス:アルゴリズム / OS / ネットワーク / DB
ユークリッドの互除法(GCD)

コンピューターサイエンス:アルゴリズム / OS / ネットワーク / DB

ソート、探索、再帰などのアルゴリズムに加え、OS (プロセス、メモリ、ファイルシステム)、ネットワーク (TCP/IP、HTTP、DNS、CDN)、データベースまで、Web エンジニアに必要な CS の基礎を一本で学べる総合コースです。エンジニア転職を目指す学習者や、CS 出身でない現役エンジニアを対象としています。約 34 時間 (1 日 30 分 × 68 日) で 135 レッスンを修了でき、修了後は技術選定やシステム設計の議論に自信を持って参加できるようになります。

1
再帰の基礎
01. 階乗(再帰)5分
02. フィボナッチ数(再帰)5分
03. 累乗(再帰)5分
04. 配列の合計(再帰)5分
05. 桁数を数える(再帰)5分
06. 文字列を逆順(再帰)5分
07. ユークリッドの互除法(GCD)5分
08. 第1章まとめクイズ — 再帰の基礎5分
2
第2章 探索
01. 線形探索で位置を返す5分
02. 二分探索 (反復版)5分
03. 二分探索 (再帰版)5分
04. lower_bound (最初に >= target の位置)5分
05. ピーク要素検索5分
06. 回転ソート配列での探索5分
07. 第2章まとめクイズ5分
3
ソート
01. バブルソート実装5分
02. 選択ソート5分
03. 挿入ソート5分
04. マージソート5分
05. クイックソート5分
06. カウントソート5分
07. 比較関数つきソート5分
08. 第3章まとめクイズ5分
4
配列 / 文字列の応用
01. 双方向ポインタで和 = K5分
02. スライド窓の最大和5分
03. 回文判定5分
04. 重複なし最長部分文字列5分
05. 大きな数の文字列乗算5分
06. アナグラムグルーピング5分
07. 第4章まとめクイズ — 配列 / 文字列の応用5分
5
クラスと OOP
01. 長方形クラス(面積と周長)5分
02. スタッククラス(push と pop)5分
03. キュークラス(enqueue と dequeue)5分
04. 単方向リンクリスト5分
05. 二分探索木 (BST) への挿入5分
06. カウンタクラス(機能合成)5分
07. 第 5 章クイズ — クラスと OOP5分
6
動的計画法 (基礎)
01. メモ化フィボナッチ5分
02. DP配列でフィボナッチ5分
03. 階段の登り方5分
04. コイン両替最小枚数5分
05. 0/1 ナップサック問題5分
06. 最長共通部分列 (LCS)5分
07. 第6章まとめクイズ5分
7
総合演習
01. ソート済み 2 配列のマージ5分
02. 配列の k 回転5分
03. カッコの妥当性5分
04. ローマ数字を整数に5分
05. 整数をローマ数字に5分
06. 雨水を溜める5分
07. 最終総まとめクイズ5分
8
[OS] Section 1. OS とは
01. コンピューターとOSの役割15分
02. OSの歴史(バッチ→マルチタスク→マルチユーザー)15分
03. カーネルとユーザーランド15分
04. システムコールの仕組み15分
05. Linux / macOS / Windows のアーキ比較15分
9
[OS] Section 2. プロセスとスレッド
01. プロセスとは15分
02. スレッドとプロセスの違い15分
03. コンテキストスイッチ15分
04. スケジューラとアルゴリズム15分
05. プロセス間通信(IPC)15分
10
[OS] Section 3. メモリ管理
01. メモリ階層(レジスタ→キャッシュ→RAM→ディスク)15分
02. 仮想メモリ15分
03. ページングとスワップ15分
04. mmap とメモリマップトファイル15分
05. ガベージコレクション概要15分
11
[OS] Section 4. ファイルシステム
01. ファイルシステムとは15分
02. i-node とディレクトリ15分
03. ext4 / APFS / NTFS の違い15分
04. ジャーナリングと耐障害性15分
05. パーミッションと所有者15分
12
[OS] Section 5. 同期と並行性
01. レースコンディション15分
02. Mutex と Semaphore15分
03. デッドロック15分
04. 非同期と並行15分
05. イベントループと epoll15分
13
[ネットワーク] ネットワークの全体像
01. ネットワークとは8分
02. OSI 7階層モデル10分
03. TCP/IP 4階層モデル9分
04. パケットとフレーム9分
05. ルーター・スイッチ・ハブ9分
14
[ネットワーク] IP とルーティング
01. IPアドレス (IPv4 / IPv6)10分
02. サブネットマスクと CIDR11分
03. NAT とプライベートIP9分
04. ルーティングと経路選択10分
05. ファイアウォール基礎9分
15
[ネットワーク] TCP / UDP
01. TCP と UDP の違い9分
02. 3-way ハンドシェイク9分
03. 輻輳制御と再送10分
04. UDP の用途 (DNS / 動画 / ゲーム)8分
05. ポート番号と well-known port9分
16
[ネットワーク] HTTP / HTTPS
01. HTTP の基本10分
02. HTTP メソッド9分
03. HTTPS と TLS ハンドシェイク10分
04. HTTP/2 と HTTP/3 (QUIC)10分
05. REST API の設計原則10分
17
[ネットワーク] DNS とドメイン
01. DNS とは8分
02. レコードタイプ10分
03. 名前解決の流れ10分
04. DNS キャッシュと TTL9分
05. CDN の仕組みと Anycast10分
18
[ネットワーク] 応用
01. ロードバランサ (L4 / L7)10分
02. プロキシとリバースプロキシ9分
03. WebSocket とリアルタイム通信9分
04. gRPC と HTTP/2 利用10分
19
[データベース] データベースの基礎
01. データベースとは8分
02. RDB と NoSQL の違い8分
03. データベースの歴史8分
04. エンティティ関係モデル (ER)8分
05. 主キー・外部キー・候補キー8分
20
[データベース] 正規化
01. 正規化とは何か8分
02. 第1正規形8分
03. 第2正規形8分
04. 第3正規形8分
05. 非正規化のトレードオフ8分
21
[データベース] インデックスと B-tree
01. インデックスの役割8分
02. B-tree の仕組み8分
03. B+tree(実際の DB 実装)8分
04. ハッシュインデックス8分
05. カバリングインデックス8分
22
[データベース] トランザクションと ACID
01. トランザクションとは8分
02. ACID 特性8分
03. 分離レベル8分
04. MVCC(マルチバージョン同時実行制御)8分
05. デッドロックと回避8分
23
[データベース] クエリ最適化
01. クエリプランナの役割8分
02. EXPLAIN の読み方8分
03. Nested Loop / Hash / Merge Join8分
04. インデックスチューニング8分
05. 統計情報とカーディナリティ8分
24
[データベース] スケーリング
01. レプリケーション8分
02. シャーディング8分
03. CAP 定理8分
04. 結果整合性8分
05. NewSQL と分散 SQL8分

ユークリッドの互除法(GCD)

12 と 18 の最大公約数は 6。これを求める最古の方法がユークリッドの互除法です。紀元前 300 年ごろに書かれた手順が、今でも最速の部類で動きます。今回の主題は「なぜこれが必ず終わるのか」です。

止め忘れると、0 で割って落ちる

互除法は割り算の余りを使い続けます。まず % の振る舞いを確かめておきます。

Python

17 % 5 # 2 余りは、割る数より必ず小さい 9 % 3 # 0 割り切れたら 0 4 % 9 # 4 割る数のほうが大きいと、そのまま残る 7 % 0 # ZeroDivisionError

最後の行が今回の落とし穴です。余りを繰り返し取っていくと、いつか必ず 0 が現れます。そこで止めると書き忘れると、次の呼び出しで 0 を割る数として渡してしまい、延々と回り続ける前にゼロ除算で落ちます。

止まらない再帰が、必ずしも再帰のエラーで落ちるとは限らない、という例です。ゼロ除算のエラーだけを見ると、割り算の書き方を間違えたように見えてしまいます。実際に足りないのは、止める条件のほうです。エラーの名前だけで原因を決めつけないでください。

余りは、必ず割る数より小さい

なぜ必ず 0 に届くのか。理由は % の 1 行目に書いた性質にあります。余りは 0 以上で、割る数より必ず小さい。だから次に持っていく数は、今の割る数より確実に小さくなります。値が同じところで足踏みすることはありません。

整数が真に小さくなり続け、下は 0 で止まっている。そうであれば、有限回で必ず 0 に着きます。境界を 1 つずつ手で追わなくても、この性質だけで「止まる」と言い切れるのが互除法の気持ちのよいところです。

48 と 18 で余りを取り続けると、こう縮みます。

プレーンテキスト

48 を 18 で割った余りは 12 18 を 12 で割った余りは 6 12 を 6 で割った余りは 0

3 回で 0 に着きました。1 から順に共通の約数を試す方法だと最悪で 18 回かかるので、桁が大きくなるほど差が開きます。数が 10 桁あっても数十回で終わる速さです。

大きい数を先に渡さなくてよい

小さいほうを先に渡してしまったら、と心配になりますが、直す必要はありません。% の 3 行目のとおり、割る数のほうが大きいと余りは元の数のままです。その結果、次の呼び出しで 2 つの引数が入れ替わり、大きいほうが先に来た状態へ自動で補正されます。

余分に 1 段降りるだけで、答えは変わりません。呼ぶ前に大小を並べ替える処理は要らない、ということです。テストには 12 と 18 の両方の順番が入っていますが、どちらも同じ答えになります。

もう一つ、片方が片方の倍数のときも特別扱いは要りません。100 と 25 なら 1 回目の余りがいきなり 0 になるので、そのまま止まります。境界に見えるケースが、実は同じ道を通っている。互除法が 2300 年生き残っているのは、この取りこぼしの無さのおかげです。

解説

多くの言語には math.gcd のような組み込みが用意されています。実務ではそちらを使いますが、中で起きていることは今回書くものと同じです。

要件

  1. 関数 gcd(a, b) を実装し、最大公約数を整数で返す
  2. for / while / 組み込み math.gcd を使わず、必ず再帰で実装する
  3. 基底ケースは b == 0 のとき a を返す

入出力例

gcd(12, 18) → 6 gcd(18, 12) → 6 gcd(7, 13) → 1 gcd(100, 25) → 25 gcd(48, 36) → 12 gcd(1, 1) → 1

ヒント

再帰呼び出しは gcd(b, a % b) の形

a と b の大小関係は気にしなくてよい。再帰の中で自動的に補正される

% は剰余演算子。Python / JS / Java / Go すべてで使える

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

関連レッスン

  • 第1章まとめクイズ — 再帰の基礎

    階乗・フィボナッチ・累乗・配列合計・桁数・文字列逆順・ユークリッド互除法の理解度を 1 問でチェックする章末クイズ。

  • 線形探索で位置を返す

    配列を先頭から走査し、目的の値が最初に現れた位置 (index) を返す線形探索を実装します。

  • バブルソート実装

    隣接する要素を比較・交換していくバブルソートを実装し、整列アルゴリズムの基本動作と計算量を学ぶ。

  • 双方向ポインタで和 = K

    ソート済み配列の両端から `left` と `right` を動かして、和が `K` になるペアを `O(n)` で見つける双方向ポインタ法を学ぶ。

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

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

  • 再帰関数が自分自身を呼び出す処理パターン
  • 引数位置引数=順番で渡す。
  • 処理計算や代入を表す長方形
  • テストバグを見つける工程
  • 関数処理に名前を付けて再利用できる単位
main.py
学習モード
エディタを読み込んでいます

メモ

ユークリッドの互除法(GCD)

⌘S で保存