📘 CodingMarble Learn

アルゴリズム設計の方法

アルゴリズムを設計するときは、まず問題をはっきりさせる。入力のデータ、ほしい出力、そして条件だ。次に、はっきりした有限の手順を、文章、箇条書き、擬似コード、フローチャートなどで書く。大きな問題は、上から小さく分けていく方法(段階的詳細化)か、テスト済みの小さな部品から組み上げる方法(ボトムアップ)で作る。代表的な手法は、力まかせ法(全部試す)、分割統治法(分ける、解く、合わせる。二分探索やマージソートのように半分にする)、貪欲法(そのとき一番よさそうな選択をする。速いが最適とは限らない)、動的計画法(小さな問題を一度だけ解いて表に保存する)、バックトラック(選んで、行き止まりなら戻す)。手法とデータ構造(配列、スタック、二分木)は、正しさと効率(時間計算量)を確かめて選ぶ。

🎬 ステップ別ストーリー

  1. まず問題をはっきりさせる。入力は8個の数。出力は一番大きい数。手順は、箱を1つずつ見て、今までで一番大きいものを覚えておくこと。
  2. 分割統治法:1から16までの数を当てるには、真ん中について聞いて、半分を捨てる。たった4回の質問で足りる。
  3. 貪欲法:入るなかで一番大きいコインをいつも取る。速いけれど、コインが1、3、4で6円を作ると3枚になり、最良の2枚にならない。
  4. 動的計画法:小さい金額から先に解いて、答えを表に保存する。表を見ると 6 = 3 + 3 が見つかる。
  5. バックトラック:道を進んで、行き止まりなら最後に選んだ分かれ道まで戻り、別の道を試す。出口に着くまでくり返す。
  6. あなたの番:金額とコインを選ぼう。予想してみよう。貪欲法で枚数は最小になるかな。DPと比べてみよう。

ヒント:3Dをドラッグすると回せます。2本指で拡大・縮小できます。

🤔 よくある疑問をスッキリ解決

コードを書く前に、なぜ入力と出力を書くの?

何が入って何が出るべきかが正確にわからないと、手順が正しいかどうかテストできないから。

16個の数が、どうして4回の質問で足りるの?

答えのたびに半分を捨てるから:16、8、4、2、1。灰色の箱が、捨てた半分を表している。

貪欲法がまちがうことがあるのに、なぜ使うの?

とても速くて簡単だし、多くの問題(ふつうのコイン、一番早く終わる活動)では正しいと証明されているから。

DPは、全部試すのとどう違うの?

小さい金額を一度だけ解いて使い回すので、すべての組み合わせを調べずに、表が少しずつ育っていく。

バックトラックは、最初からやり直すの?

ちがう。まだ試していない道がある最後の分かれ道まで戻って、そこから続ける。

自分のコインで貪欲法が使えるかは、どうやって知るの?

たくさんの金額でDPと比べる。自由に遊ぶステップで、コイン1、7、10を試してみよう。

問題の仕様:入力、出力、手順

コードを書く前に、問題を正確に説明しよう。これを仕様という。

手順を書く

アルゴリズムとは、どんな正しい入力でも正しい出力に変える、有限で明確な手順の並びだ。次のように書ける。

小さな入力で手計算して確かめよう。変わった場合(全部同じ、負の数、数が1個だけ)も試す。

トップダウン設計とボトムアップ設計

トップダウン(段階的詳細化):作業全体から始めて、いくつかの大きな手順に分け、それぞれをさらに分けて、コードにしやすくなるまで続ける。例:「成績表を作る」→ 点数を読む → 平均を出す → 評価をつける → 印刷する。

ボトムアップ:先に、再利用できる小さな部品(最大値を探す関数、並べ替える関数)を作ってテストし、それらをつなげて全体のプログラムにする。

実際の開発では両方を混ぜる。計画はトップダウン、作ってテストするのはボトムアップだ。

分割統治法と半分にする方法

分割統治法は3つの動きでできている。問題を同じ種類の小さな部分に分ける。それぞれを(たいてい再帰で)解く。答えを合わせる。

貪欲法

貪欲法は、そのとき一番よさそうな選択をして、あとで変えないやり方だ。

でも貪欲法はいつも正しいとは限らない。コインが1、3、4のとき、6を貪欲に作ると 4 + 1 + 1(3枚)だが、3 + 3 なら2枚で済む。貪欲法を信じるには、正しいと証明するか、確実な方法と比べてテストする必要がある。

動的計画法とバックトラック

動的計画法(DP)

同じ小さな問題が何度も出てくるときは、それぞれを一度だけ解いて、答えを表に保存する。金額 a の最小枚数は best[a] = 1 + min(best[a - c])(c ≤ a となるコイン c すべてについて)で、best[0] = 0 から始める。コインが1、3、4なら best = 0, 1, 2, 1, 1, 2, 2 になる。表を小さい方から大きい方へうめるのがボトムアップ。答えをメモしながら再帰するのがトップダウン(メモ化)だ。くわしくは別の「動的計画法」の授業を見よう。

バックトラック

解を、選択を1つずつ重ねて作る。選んだものがルールに反したり、行き止まりになったら、それを取り消して次の候補を試す。迷路、数独、Nクイーン、すべての部分集合を並べる問題などに使う。かしこい力まかせ法で、うまくいかない枝をまるごと飛ばせる。

力まかせ法

考えられる答えをすべて試す。いつも正しいが、遅すぎることが多い(部分集合は2ⁿ個、並べ方は n! 通り)。

手法の選び方:正しさ、効率、データ構造

手法使うとき例ふつうの時間
力まかせ法入力がとても小さい3けたの暗証番号を全部試す2ⁿ や n! が多い
分割統治法部分どうしが独立している二分探索、マージソートO(log n)、O(n log n)
貪欲法その場の最良の選択が安全だと証明できる活動選択、おつりO(n log n)
動的計画法小さな問題がくり返し出るコイン問題、最短経路表の大きさ
バックトラックルールつきの探索迷路、数独指数的。ただし枝を切る

理由を説明する

正しさ:アルゴリズムが必ず止まり、正しい出力を出すことを示す(ループ不変条件、証明、変わった場合のテスト)。効率:n が大きくなるときの手順の数を数え(ビッグオー)、ほかの方法と比べる。

データ構造が助けてくれる

配列は表に(DP)、スタックはバックトラックに(戻る場所を覚える)、キューは1段ずつの探索に使う。二分木は、各ノードの子が最大2つになるようにデータをしまう。二分探索木では、小さいキーは左、大きいキーは右に置くので、探すたびに1段ごとに仕事が半分になる。二分探索と同じ考え方だ。

やってみよう:コインと数当てゲーム

  1. 友だちと1から100までの数当てゲームをしよう。いつも真ん中について聞く。7回の質問でいつも勝てるかな?(2⁷ = 128。)
  2. コインが1、3、4のとき、金額0から10までのDP表を紙に書こう。貪欲法はどこで失敗する?
  3. 3Dの最後のステップを開こう。コイン1、7、10で金額14を試す。貪欲法は 10 + 1 + 1 + 1 + 1、DPは 7 + 7 になる。
  4. 「リストの中で一番小さい数を探す」手順を書いて、5、5、5 の場合と、数が1個だけの場合でテストしよう。

重要な公式と用語

例題

1. n個の数の中で一番大きい数を探す問題の仕様と手順を書こう。

入力:n ≥ 1 個の数。出力:一番大きい数。手順:1. best ← 最初の数。2. ほかの各数 x について、x > best なら best ← x。3. best を出力する。4, 9, 2, 7, 12, 5, 10, 3 なら、7回の比較で 12 が出力される。

2. 1から1000までの数を見つけるのに、半分にする方法で何回質問が必要?

質問のたびに範囲が半分になる:1000 → 500 → 250 → 125 → 63 → 32 → 16 → 8 → 4 → 2 → 1。つまり10回(2¹⁰ = 1024 ≥ 1000)。

3. 50、20、10、5、2、1のコインで、87を貪欲法で払おう。

50(残り37)、20(17)、10(7)、5(2)、2(0):50 + 20 + 10 + 5 + 2 = 5枚。

4. コイン1、3、4で、金額7までのDP表をうめよう。

best[0]=0、[1]=1、[2]=2、[3]=1、[4]=1、[5]=min(best4, best2, best1)+1=2、[6]=min(best5, best3, best2)+1=2、[7]=min(best6, best4, best3)+1=2(3 + 4)。

5. 活動(開始-終了):A 9-11、B 10-12、C 11-13、D 12-14、E 13-15。重ならないように、できるだけ多く選ぼう。

終わるのが一番早いものを選ぶ貪欲法:A(11に終了)、次に C(11に開始、13に終了)、次に E(13に開始)。3つの活動:A、C、E。

6. クラスの平均点と最高得点の生徒を知らせるプログラムを、トップダウンで計画しよう。

レベル1:データを読む → 計算する → 印刷する。レベル2:名前と点数をリストに読みこむ。合計と平均を計算する。最高点とその名前を探す。両方を印刷する。そのあと各部分をコードにして、ボトムアップでテストする。

よくある間違い

練習クイズ

1. 問題の仕様に必ず書くものは?
2. 整列した16個を二分探索するとき、最大でおよそ何回調べる?
3. そのときいちばんよさそうな選択をいつも取る手法はどれ?
4. 動的計画法がうまく働くのはどんなとき?
5. 迷路の探索で、行き止まりのあとに最後の分かれ道まで戻ることを何という?

練習:自分で答えてみよう

答えを入力するか選んで、「チェック」を押そう。困ったらヒントを見てね。解答は答えたあとに表示されます。

よくある質問

アルゴリズム設計の主な手法は何?

力まかせ法、分割統治法、貪欲法、動的計画法、バックトラック。入力と出力を決めてから選ぶ。

貪欲法と動的計画法はどう違うの?

貪欲法は、各段階でいちばんよさそうな選択を1つして、二度と見直さない。DPは小問題ごとにすべての選択を考え、最良の答えを保存するので、小問題が重なるときに本当の最適解が見つかる。

トップダウン設計とボトムアップ設計の違いは?

トップダウンは作業全体を小さな手順に分ける。ボトムアップは小さな部品を先に作ってテストし、つなげていく。たいていのプログラムは両方を使う。

学ぶ場所

PolandSzkoła podstawowa, klasa VIIUnderstanding, analysing and solving problems
PolandSzkoła podstawowa, klasa VIIIUnderstanding, analysing and solving problems
PolandLiceum ogólnokształcące, klasa IUnderstanding, analysing and solving problems
China高三Electives (选修)

先に学ぼう

次に学ぼう

関連する授業

Computer Scienceの授業一覧