SlideShare a Scribd company logo
1 of 179
アルゴリズムのお勉強
兼 前期中間対策
※注意書き
• 確実にテスト対策になる確証はありません
• あくまでお勉強用です
• 過去の経験やノートを参考にしています
• あと変なノリが含まれます
• あと、責任は取りません…というか取れません
それでもいいなら進めていってください。
はじめにパターンの考察
• 用語の記述
→ アルゴリズム系の用語
• アルゴリズムの記述
→ 疑似言語の穴埋め?
→ C言語の穴埋め?
→ 動作の記述
まずテスト範囲から
出そうなパターンの考察です。
はじめにパターンの考察
• 用語の記述
→ アルゴリズム系の用語
• アルゴリズムの記述
→ 疑似言語の穴埋め?
→ C言語の穴埋め?
→ 動作の記述
基本的に用語などの記述は出ますね。
はじめにパターンの考察
• 用語の記述
→ アルゴリズム系の用語
• アルゴリズムの記述
→ 疑似言語の穴埋め?
→ C言語の穴埋め?
→ 動作の記述
アルゴリズムとは、
問題/問題例集合とは、
正しいアルゴリズムとはetc…
はじめにパターンの考察
• 用語の記述
→ アルゴリズム系の用語
• アルゴリズムの記述
→ 疑似言語の穴埋め?
→ C言語の穴埋め?
→ 動作の記述
おそらくですが、6割強は授業でやった
アルゴリズム関係になると思います。
はじめにパターンの考察
• 用語の記述
→ アルゴリズム系の用語
• アルゴリズムの記述
→ 疑似言語の穴埋め?
→ C言語の穴埋め?
→ 動作の記述
まず疑似言語の記述です。
穴埋めの可能性もありますが、
丸暗記した方がいいかもしれません。
はじめにパターンの考察
• 用語の記述
→ アルゴリズム系の用語
• アルゴリズムの記述
→ 疑似言語の穴埋め?
→ C言語の穴埋め?
→ 動作の記述
同様にC言語ですが、
こちらは穴埋めの可能性が高いと思います。
はじめにパターンの考察
• 用語の記述
→ アルゴリズム系の用語
• アルゴリズムの記述
→ 疑似言語の穴埋め?
→ C言語の穴埋め?
→ 動作の記述
最後に、動作の記述ですね。
経験的にはここができなければ死にます。
はじめにパターンの考察
• 用語の記述
→ アルゴリズム系の用語
• アルゴリズムの記述
→ 疑似言語の穴埋め?
→ C言語の穴埋め?
→ 動作の記述
ということで、動作の記述を中心に
解説していこうかと思います。
用語の方はノートを参考に暗記してください。
はじめにパターンの考察
• 用語の記述
→ アルゴリズム系の用語
• アルゴリズムの記述
→ 疑似言語の穴埋め?
→ C言語の穴埋め?
→ 動作の記述
さっそくエラトステネスのふるいから
説明していきます。
エラトステネスのふるい
• 素数検出法のひとつ
• 主に素数の羅列に使われる 基本的には配列から
2の倍数, 3の倍数, 5の倍数~
をのけていくと…という考え方…
32 4 N…98765
エラトステネスのふるい
• 素数検出法のひとつ
• 主に素数の羅列に使われる 簡単に実践してみると…
まず先頭である2の倍数をのけます~
32 4 N…98765
30 0 N…90705
エラトステネスのふるい
• 素数検出法のひとつ
• 主に素数の羅列に使われる
次に先頭である3の倍数をのけます~
30 0 N…90705
30 0 N…00705
エラトステネスのふるい
• 素数検出法のひとつ
• 主に素数の羅列に使われる
次の4はすでに0だからパスします。
00 0 N…00705
00 0 N…00705
エラトステネスのふるい
• 素数検出法のひとつ
• 主に素数の羅列に使われる
次の先頭は5~
00 0 N…00705
00 0 N…00700
エラトステネスのふるい
• 素数検出法のひとつ
• 主に素数の羅列に使われる
6はなくて7~
00 0 N…00700
00 0 N…00000
エラトステネスのふるい
• 素数検出法のひとつ
• 主に素数の羅列に使われる このような感じで、倍数を消していった
2, 3, 5, 7… が素数になります。
00 0 N…00000
00 0 N…00000
エラトステネスのふるい
• 素数検出法のひとつ
• 主に素数の羅列に使われる これらを配列に入れることで
素数のリストができますね。
00 0 N…00000
00 0 N…00000
エラトステネスのふるい
入力 : 自然数n
出力 : n以下の素数の集合S
• 1 2~nの自然数のリストLを作る;
• 2 while L != Φ do
• 3 | Lの最小要素xをSに加える;
• 4 | x自身とxの倍数をリストLから除去する;
• 5 end
疑似言語を記述しますが、
若干表現が異なる点に注意してください。
エラトステネスのふるい
入力 : 自然数n
出力 : n以下の素数の集合S
• 1 2~nの自然数のリストLを作る;
• 2 while L != Φ do
• 3 | Lの最小要素xをSに加える;
• 4 | x自身とxの倍数をリストLから除去する;
• 5 end
まず入力は1つの自然数ですね。
エラトステネスのふるい
入力 : 自然数n
出力 : n以下の素数の集合S
• 1 2~nの自然数のリストLを作る;
• 2 while L != Φ do
• 3 | Lの最小要素xをSに加える;
• 4 | x自身とxの倍数をリストLから除去する;
• 5 end
出力は素数のリストです。
2, 3, 5, 7…と入っていきます。
エラトステネスのふるい
入力 : 自然数n
出力 : n以下の素数の集合S
• 1 2~nの自然数のリストLを作る;
• 2 while L != Φ do
• 3 | Lの最小要素xをSに加える;
• 4 | x自身とxの倍数をリストLから除去する;
• 5 end
まずふるいにかける、
自然数のリストを用意します。
C言語なら配列ですね。
エラトステネスのふるい
入力 : 自然数n
出力 : n以下の素数の集合S
• 1 2~nの自然数のリストLを作る;
• 2 while L != Φ do
• 3 | Lの最小要素xをSに加える;
• 4 | x自身とxの倍数をリストLから除去する;
• 5 end
Lが空集合でない間、
つまりすべてが0でない間繰り返します。
エラトステネスのふるい
入力 : 自然数n
出力 : n以下の素数の集合S
• 1 2~nの自然数のリストLを作る;
• 2 while L != Φ do
• 3 | Lの最小要素xをSに加える;
• 4 | x自身とxの倍数をリストLから除去する;
• 5 end
C言語では最小要素がn以下でない時…
とでも表現しましょうか。
エラトステネスのふるい
入力 : 自然数n
出力 : n以下の素数の集合S
• 1 2~nの自然数のリストLを作る;
• 2 while L != Φ do
• 3 | Lの最小要素xをSに加える;
• 4 | x自身とxの倍数をリストLから除去する;
• 5 end
最小要素をSに加えることで
素数を保管します。
エラトステネスのふるい
入力 : 自然数n
出力 : n以下の素数の集合S
• 1 2~nの自然数のリストLを作る;
• 2 while L != Φ do
• 3 | Lの最小要素xをSに加える;
• 4 | x自身とxの倍数をリストLから除去する;
• 5 end
その数字の倍数だから素数じゃない、
という考え方で除去します。
C言語では0にしていくことで実装します。
エラトステネスのふるい
入力 : 自然数n
出力 : n以下の素数の集合S
• 1 2~nの自然数のリストLを作る;
• 2 while L != Φ do
• 3 | Lの最小要素xをSに加える;
• 4 | x自身とxの倍数をリストLから除去する;
• 5 end
あとは繰り返して終わりですね。
エラトステネスのふるい
• 課題1のリスト
プリント通りだとC言語の配列は
上のように確保します。
今回は下のリストの方法で解説します。
-- 2 N…76543
32 4 N…98765
エラトステネスのふるい
動作例
まず最小要素を見つけます。
配列に追加したらその倍数を
削除(0に)していけばいいですね。
32 4 N…98765
02 0 0…00000
エラトステネスのふるい
動作例
最終的にこんな感じになります。
00 0 N…00000
32 5 0…191713117
エラトステネスのふるい
C言語の記述
C言語は基本暗記か
流れを覚えるしかないです。
エラトステネスのふるい
C言語の記述
強いて言えばfor文の条件式、
配列の大きさや添字などが
出やすい傾向にあると思います。
エラトステネスのふるい→素因数分解
素数で割っていく→素因数分解
素数のリストがあるのである数を素数で順
に割っていけば素因数分解ができる…
という至って簡単な問題です。
エラトステネスのふるい→素因数分解
C言語
強いて言えばうちらの班の解答を見てね~
となりますが一応説明します。
エラトステネスのふるい→素因数分解
// Sの中にxの約数があればAに追加しxの値を更新する
// 8行目の約数とは、一番初めに見つけた約数であると考えた
for (i = 0; i < nS; i++) {
if (x % S[i] == 0) {
x /= S[i];
A[(*m)++] = S[i];
break;
}
}
これが原文。
ちょっと窮屈。
エラトステネスのふるい→素因数分解
// Sの中にxの約数があればAに追加しxの値を更新する
// 8行目の約数とは、一番初めに見つけた約数であると考えた
for (i = 0; i < nS; i++) {
if (x % S[i] == 0) {
x /= S[i];
A[(*m)++] = S[i];
break;
}
}
基本的には素数のリストの下から順番に
ある数xを割っていきます。
エラトステネスのふるい→素因数分解
// Sの中にxの約数があればAに追加しxの値を更新する
// 8行目の約数とは、一番初めに見つけた約数であると考えた
for (i = 0; i < nS; i++) {
if (x % S[i] == 0) {
x /= S[i];
A[(*m)++] = S[i];
break;
}
}
もしxが倍数だったら…
エラトステネスのふるい→素因数分解
// Sの中にxの約数があればAに追加しxの値を更新する
// 8行目の約数とは、一番初めに見つけた約数であると考えた
for (i = 0; i < nS; i++) {
if (x % S[i] == 0) {
x /= S[i];
A[(*m)++] = S[i];
break;
}
}
まずxを割っちゃいます。
エラトステネスのふるい→素因数分解
// Sの中にxの約数があればAに追加しxの値を更新する
// 8行目の約数とは、一番初めに見つけた約数であると考えた
for (i = 0; i < nS; i++) {
if (x % S[i] == 0) {
x /= S[i];
A[(*m)++] = S[i];
break;
}
}
そして出力配列にその約数を追加します!
これが小さい数から出力されるわけです。
エラトステネスのふるい→素因数分解
// Sの中にxの約数があればAに追加しxの値を更新する
// 8行目の約数とは、一番初めに見つけた約数であると考えた
for (i = 0; i < nS; i++) {
if (x % S[i] == 0) {
x /= S[i];
A[(*m)++] = S[i];
break;
}
}
そしてbreak;
理由として、2で割ったけどまだ2で割れる可
能性を考慮してもう一度2から割り始めます。
エラトステネスのふるい→素因数分解
// x + 1 以上のすべての要素をSから除去する
// nSを小さくすること→リストから排除すること
for (i = 0; i < nS; i++)
if (S[i] > x)
nS = i;
そして上の記述に戻ります。
ここがリストから排除するとこです。
エラトステネスのふるい→素因数分解
// x + 1 以上のすべての要素をSから除去する
// nSを小さくすること→リストから排除すること
for (i = 0; i < nS; i++)
if (S[i] > x)
nS = i;
つまりわざわざ素数のリストの中身を0で上
書きしなくていいというわけです。
エラトステネスのふるい→素因数分解
// x + 1 以上のすべての要素をSから除去する
// nSを小さくすること→リストから排除すること
for (i = 0; i < nS; i++)
if (S[i] > x)
nS = i;
ある数で割れるたびに
その数より大きい素数は捨てちゃえ~
というのがこの行。
エラトステネスのふるい→素因数分解
// x + 1 以上のすべての要素をSから除去する
// nSを小さくすること→リストから排除すること
for (i = 0; i < nS; i++)
if (S[i] > x)
nS = i;
まあ日本語の問題かな?
この解釈も割と無理ありますが。
文字照合
• 文字列の中から
特定の文字が出現する位置を返す
「”abcdefg”の中の’c’は何番目?」
「2番目(添字)です」
問題の文字照合および文字列照合。
ここ理解しとかないと点数吹っ飛びます。
文字照合
• 文字列の中から
特定の文字が出現する位置を返す
「”abcdefg”の中の’c’は何番目?」
「2番目(添字)です」
下の例みたいな感じですね。
文字照合
• 文字列の中から
特定の文字が出現する位置を返す
「”abcdefg”の中の’z’は何番目?」
「7番目(添字)です」
ここで一点注意。
見つからなかった場合は
文字列の長さを返します。
動作例
文字照合
as c ¥0s ecifir
c
c
c
動作は非常にシンプルで、
前から探索していきます。
例は”sacrifice”から’c’です。
動作例
文字照合
as c ¥0s ecifir
c
c
c
1文字目SとCを比べて、異なるので、
三角でCを囲みましょう。
動作例
文字照合
as c ¥0s ecifir
c
c
c
同様に2文字目AとCを比べて、異なるので、
三角でCを囲みましょう。
動作例
文字照合
as c ¥0s ecifir
c
c
c
3文字目はCとCで等しいので
丸で囲みましょう。
出力は2になります。
動作例
文字照合
as c ¥0s ecifir
c
c
c
ちなみに照合回数は3回となります。
囲んだ数が照合回数となります。
動作例
文字照合
逆に見つからない場合。
今回はZを探してみよう。
as c ¥0s ecifir
z
z
z
z
動作例
文字照合
最後の’¥0’とは比較を行わないので、
出力値は9、照合回数も9になります。
as c ¥0s ecifir
z
z
z
z
文字列照合
• 文字列の中から
特定の文字列が出現する位置を返す
「”abcdefg”の中の’bcd’は何番目?」
「1番目(添字)です」
次に文字列照合。
今回は文字列を探します。
文字列照合
• 文字列の中から
特定の文字列が出現する位置を返す
「”abcdefg”の中の’xyz’は何番目?」
「7番目(添字)です」
見つからない場合は同様に文字列の長さを
出力します。
文字列照合
as c ¥0s ecifir
c e まず1文字目の比較を行います。
いきなり異なるから次に行きましょう。
文字列照合
as c ¥0s ecifir
c e
c e
2文字目も異なりますね。
文字列照合
as c ¥0s ecifir
c e
c e
c e
3文字目は、Cは同じですがEが異なりました。
文字列照合
as c ¥0s ecifir
c e
c e
c e
c e
4文字目はCが異なります。
文字列照合
as c ¥0s ecifir
c e
c e
c e
c e c e
同様にやっていくと8文字目で
両方一致しましたね。
文字列照合
as c ¥0s ecifir
c e
c e
c e
c e c e
文字の位置は7で
照合回数は10回になります。
文字列照合
as c ¥0s ecifir
z z
z z
z z
z z z z
次に見つからない場合。
“zz”を探してみましょう。
z z
文字列照合
as c ¥0s ecifir
z z
z z
z z
z z z z
見つからなかったので、出力は9で
照合回数は9になりますね。
z z
文字列照合
入力 : テキストS, 単語W
出力 : テキストS内の単語Wの場所
• 1 i ← 0; j ← 0;
• 2 while i + j < |s| do
• 3 | if W[j] = S[i + j] then
• 4 | | j ← j + 1;
• 5 | | もし j = |W|ならばiを出力して終了;
• 6 | end
そして疑似言語。
枠の都合上まずは6まで。
文字列照合
入力 : テキストS, 単語W
出力 : テキストS内の単語Wの場所
• 1 i ← 0; j ← 0;
• 2 while i + j < |s| do
• 3 | if W[j] = S[i + j] then
• 4 | | j ← j + 1;
• 5 | | もし j = |W|ならばiを出力して終了;
• 6 | end
入力、出力の説明はもういいですね。
文字列照合
入力 : テキストS, 単語W
出力 : テキストS内の単語Wの場所
• 1 i ← 0; j ← 0;
• 2 while i + j < |s| do
• 3 | if W[j] = S[i + j] then
• 4 | | j ← j + 1;
• 5 | | もし j = |W|ならばiを出力して終了;
• 6 | end
このiはテキストS用の添字になります。
Sの何文字目を探索しているかを表します。
文字列照合
入力 : テキストS, 単語W
出力 : テキストS内の単語Wの場所
• 1 i ← 0; j ← 0;
• 2 while i + j < |s| do
• 3 | if W[j] = S[i + j] then
• 4 | | j ← j + 1;
• 5 | | もし j = |W|ならばiを出力して終了;
• 6 | end
そしてjは単語Wのどこと比較しているかを
表す変数です。
文字列照合
入力 : テキストS, 単語W
出力 : テキストS内の単語Wの場所
• 1 i ← 0; j ← 0;
• 2 while i + j < |s| do
• 3 | if W[j] = S[i + j] then
• 4 | | j ← j + 1;
• 5 | | もし j = |W|ならばiを出力して終了;
• 6 | end
この条件式はテキストSの文字の範囲であ
る限り照合を繰り返すという意味になります。
文字列照合
入力 : テキストS, 単語W
出力 : テキストS内の単語Wの場所
• 1 i ← 0; j ← 0;
• 2 while i + j < |s| do
• 3 | if W[j] = S[i + j] then
• 4 | | j ← j + 1;
• 5 | | もし j = |W|ならばiを出力して終了;
• 6 | end
例えば”abc”なら’a’と’b’と’c’の3カ所から
照合が開始できますね。
文字列照合
入力 : テキストS, 単語W
出力 : テキストS内の単語Wの場所
• 1 i ← 0; j ← 0;
• 2 while i + j < |s| do
• 3 | if W[j] = S[i + j] then
• 4 | | j ← j + 1;
• 5 | | もし j = |W|ならばiを出力して終了;
• 6 | end
ここが実際に文字の比較を
行っているところになります。
文字列照合
入力 : テキストS, 単語W
出力 : テキストS内の単語Wの場所
• 1 i ← 0; j ← 0;
• 2 while i + j < |s| do
• 3 | if W[j] = S[i + j] then
• 4 | | j ← j + 1;
• 5 | | もし j = |W|ならばiを出力して終了;
• 6 | end
文字が等しければさらに続けて照合を行お
うとします。
文字列照合
入力 : テキストS, 単語W
出力 : テキストS内の単語Wの場所
• 1 i ← 0; j ← 0;
• 2 while i + j < |s| do
• 3 | if W[j] = S[i + j] then
• 4 | | j ← j + 1;
• 5 | | もし j = |W|ならばiを出力して終了;
• 6 | end
このとき探索する単語Wの長さなら、
すでに一致しているので終了です。
文字列照合
入力 : テキストS, 単語W
出力 : テキストS内の単語Wの場所
• 1 i ← 0; j ← 0;
• 2 while i + j < |s| do
• 3 | if W[j] = S[i + j] then
• 4 | | j ← j + 1;
• 5 | | もし j = |W|ならばiを出力して終了;
• 6 | end
例えば”abc”なら3文字照合できたら、
正解を見つけたことになりますね。
文字列照合
• 7 | else
• 8 | | i ← i + 1;
• 9 | | j ← 0;
• 10 | end
• 11 end
• 12 end
後半部分は文字列の照合に
失敗した場合です。
文字列照合
• 7 | else
• 8 | | i ← i + 1;
• 9 | | j ← 0;
• 10 | end
• 11 end
• 12 end
もし文字列の探索が異なっていたら…
文字列照合
• 7 | else
• 8 | | i ← i + 1;
• 9 | | j ← 0;
• 10 | end
• 11 end
• 12 end
テキストSでの照合開始位置をずらして…
文字列照合
• 7 | else
• 8 | | i ← i + 1;
• 9 | | j ← 0;
• 10 | end
• 11 end
• 12 end
単語Wの比較開始位置も戻すだけ。
簡単ですね。
あとはwhile文の限り照合を続けます。
文字列照合
int StringMatching(char * p, char * q){
int i, j, s, w;
i = 0; j = 0;
s = length(p); // |S|
w = length(q); // |W|
while (i + j < s){
if (q[j] == p[i + j]){
j++;
if (j == w)
return i; // 文字列が見つかった
}
else{ // 次の場所から照合
i++;
j = 0;
}
}
return s; // 文字列が見つからなかった
}
あんまり参考にならないですが
一応C言語乗せときます。
文字列照合 (KMP法)
そしてKMP法です。
より効率的な文字列探索を
行うことができます。
• 文字列探索の効率の改善
• パターンテーブルなるものを作成する
誰だ「カナマジプリティ」とか言ったやつ
文字列照合 (KMP法)
簡単に言えば途中まで照合できてるのに、
わざわざ先頭に戻さなくてもいいよ~という
考え方になります。
• 文字列探索の効率の改善
• パターンテーブルなるものを作成する
誰だ「カナマジプリティ」とか言ったやつ
文字列照合 (KMP法)
as c ¥0ecifir
では今回は”ifif”を探してみましょう。
¥0fifi
文字列照合 (KMP法)
as c ¥0ecifir
とりあえず1文字目で異なるところは
次へと進んでいきます。
¥0fifi
¥0fifi
¥0fifi
¥0fifi
¥0fifi
文字列照合 (KMP法)
as c ¥0ecifir
5回目の照合では3文字まで同じでした。
つまり4文字目で異なりました。
¥0fifi
¥0fifi
¥0fifi
¥0fifi
¥0fifi
文字列照合 (KMP法)
as c ¥0ecifir
6回目の照合ではいつもと違うところから
比較を開始します。
これがKMP法です。
¥0fifi
¥0fifi
¥0fifi
¥0fifi
¥0fifi
¥0fifi
文字列照合 (KMP法)
as c ¥0ecifir
どうして’f’から比較を開始するでしょうか。
¥0fifi
¥0fifi
¥0fifi
¥0fifi
¥0fifi
¥0fifi
文字列照合 (KMP法)
as c ¥0ecifir
そういえばここで’i’を比較してますね。
¥0fifi
¥0fifi
¥0fifi
¥0fifi
¥0fifi
¥0fifi
文字列照合 (KMP法)
as c ¥0ecifir
つまり、途中で異なった場合に
どこから開始するか?
という情報がKMP法では必要になります。
¥0fifi
¥0fifi
¥0fifi
¥0fifi
¥0fifi
¥0fifi
文字列照合 (KMP法)
それがパターンテーブルになるわけですね。
• 文字列探索の効率の改善
• パターンテーブルなるものを作成する
文字列照合 (KMP法)
“ifif”ではパターンテーブルは
このようになります。
• 文字列探索の効率の改善
• パターンテーブルなるものを作成する
fifi
100-
文字列照合 (KMP法)
1文字目から3文字目までは0、
つまり通常通り添字が0、
1文字目から比較を開始します。
• 文字列探索の効率の改善
• パターンテーブルなるものを作成する
fifi
100-
文字列照合 (KMP法)
ただし4文字目の’f’に限り、
すでに’i’を照合しているので、
添字1、2文字目から比較するわけです。
• 文字列探索の効率の改善
• パターンテーブルなるものを作成する
fifi
100-
文字列照合 (KMP法)
このパターンテーブルですが、
直前の文字が1文字目から何文字同じか、
という計算で求められます。
• 文字列探索の効率の改善
• パターンテーブルなるものを作成する
fifi
100-
文字列照合 (KMP法)
とりあえずパターン照合テーブルの
疑似言語を見てみましょう。
入力 : 単語W
出力 : パターン照合テーブルT
• 1 T[0] ← -1;
• 2 for each 1 <= j <= |W| do
• 3 | k ← j – 1;
• 4 | while W[0~k-1] != W[j-k~j-1] and k > 0
• 5 | | k ← k – 1;
• 6 | end
• 7 | T[j] ← k;
• 8 end
文字列照合 (KMP法)
1文字目はそもそも
比較対象がないので例外となります。
入力 : 単語W
出力 : パターン照合テーブルT
• 1 T[0] ← -1;
• 2 for each 1 <= j <= |W| do
• 3 | k ← j – 1;
• 4 | while W[0~k-1] != W[j-k~j-1] and k > 0
• 5 | | k ← k – 1;
• 6 | end
• 7 | T[j] ← k;
• 8 end
文字列照合 (KMP法)
処理は単語Wのすべての文字に対して行う
という意味です。
入力 : 単語W
出力 : パターン照合テーブルT
• 1 T[0] ← -1;
• 2 for each 1 <= j <= |W| do
• 3 | k ← j – 1;
• 4 | while W[0~k-1] != W[j-k~j-1] and k > 0
• 5 | | k ← k – 1;
• 6 | end
• 7 | T[j] ← k;
• 8 end
文字列照合 (KMP法)
kはj-1、つまり直前の文字列を指します。
入力 : 単語W
出力 : パターン照合テーブルT
• 1 T[0] ← -1;
• 2 for each 1 <= j <= |W| do
• 3 | k ← j – 1;
• 4 | while W[0~k-1] != W[j-k~j-1] and k > 0
• 5 | | k ← k – 1;
• 6 | end
• 7 | T[j] ← k;
• 8 end
文字列照合 (KMP法)
このとき左辺は直前の文字まで、
右辺は自身を含む左方向数文字がそれと
等しいか比較します。
入力 : 単語W
出力 : パターン照合テーブルT
• 1 T[0] ← -1;
• 2 for each 1 <= j <= |W| do
• 3 | k ← j – 1;
• 4 | while W[0~k-1] != W[j-k~j-1] and k > 0
• 5 | | k ← k – 1;
• 6 | end
• 7 | T[j] ← k;
• 8 end
文字列照合 (KMP法)
さらに比較する文字数が多いならば、
さらに文字数を減らして確かめます。
入力 : 単語W
出力 : パターン照合テーブルT
• 1 T[0] ← -1;
• 2 for each 1 <= j <= |W| do
• 3 | k ← j – 1;
• 4 | while W[0~k-1] != W[j-k~j-1] and k > 0
• 5 | | k ← k – 1;
• 6 | end
• 7 | T[j] ← k;
• 8 end
文字列照合 (KMP法)
While文の条件式より、
より多くの一致をしたものがパターン照合
テーブルへと代入されますね。
入力 : 単語W
出力 : パターン照合テーブルT
• 1 T[0] ← -1;
• 2 for each 1 <= j <= |W| do
• 3 | k ← j – 1;
• 4 | while W[0~k-1] != W[j-k~j-1] and k > 0
• 5 | | k ← k – 1;
• 6 | end
• 7 | T[j] ← k;
• 8 end
文字列照合 (KMP法)
1文字目は例外です。
• 文字列探索の効率の改善
• パターンテーブルなるものを作成する
fifi
100-
文字列照合 (KMP法)
‘f’の時は計算過程で0になります。
疑似言語の3でk=0となるますね。
• 文字列探索の効率の改善
• パターンテーブルなるものを作成する
fifi
100-
文字列照合 (KMP法)
次の’i’ですが、K=1なので1文字目の’I’と2文
字目の’f’の1文字分の比較となりますね。
なお、異なるので0となりますが…
• 文字列探索の効率の改善
• パターンテーブルなるものを作成する
fifi
100-
fifi
fifi
W[0~0]W[0~k-1]
W[j-k~j-1] W[1~1]
文字列照合 (KMP法)
件の’f’ですが、まずk=2なので
2文字分比較します。
これは異なるのでk=1にします。
• 文字列探索の効率の改善
• パターンテーブルなるものを作成する
fifi
100-
fifi
fifi
W[0~1]W[0~k-1]
W[j-k~j-1] W[1~2]
文字列照合 (KMP法)
K=1の時は1文字目の’i’と
3文字目の’i’が等しいですね。
つまりk=1をテーブルに代入します。
• 文字列探索の効率の改善
• パターンテーブルなるものを作成する
fifi
100-
fifi
fifi
W[0~0]W[0~k-1]
W[j-k~j-1] W[2~2]
文字列照合 (KMP法)
こうしてパターンテーブルが
作成されるました。
• 文字列探索の効率の改善
• パターンテーブルなるものを作成する
fifi
100-
文字列照合 (KMP法)
一応C言語のソースリストです。
疑似言語と同じですね。
void PattenTable(char * w, int * t){
int j, k, n;
// はじめ文字に限り特別
t[0] = -1;
n = strlen(w);
// 文字の数だけ処理を行う
for(j = 1; j < n; j++){
// kは処理対象の一つ前を表す
k = j - 1;
// 部分文字列を検索
while(equalse(w, 0, k - 1, j - k) == 0 && k > 0){
k = k - 1;
}
t[j] = k;
}
}
文字列照合 (KMP法)
強いて言えばこの関数は部分文字列が正し
いか確かめる関数ですね。
void PattenTable(char * w, int * t){
int j, k, n;
// はじめ文字に限り特別
t[0] = -1;
n = strlen(w);
// 文字の数だけ処理を行う
for(j = 1; j < n; j++){
// kは処理対象の一つ前を表す
k = j - 1;
// 部分文字列を検索
while(equalse(w, 0, k - 1, j - k) == 0 && k > 0){
k = k - 1;
}
t[j] = k;
}
}
バブルソート
ということで…
翻訳地獄だったバブルソートです。
• ソートアルゴリズムの一種
• 左右で大小関係が異なれば交換
バブルソート
ソートアルゴリズムの説明は
必要ないですよね。
昇順、降順に並べるアルゴリズムです。
• ソートアルゴリズムの一種
• 左右で大小関係が異なれば交換
バブルソート
基本的には大小関係が異なれば
左右で入れ替えるだけ…
という至って単純な仕組みです。
• ソートアルゴリズムの一種
• 左右で大小関係が異なれば交換
バブルソート
この例では昇順に並べます。
左から2と3, 3と5は正しいですね。
でも5と4が逆ですよね。
• ソートアルゴリズムの一種
• 左右で大小関係が異なれば交換
4532 1
バブルソート
ならひっくり返してしまいましょう。
これで4と5の大小関係は正しくなります。
• ソートアルゴリズムの一種
• 左右で大小関係が異なれば交換
5432 1
バブルソート
ひっくり返した時は、もう一度左端から
大小関係を確認していきます。
• ソートアルゴリズムの一種
• 左右で大小関係が異なれば交換
5432 1
バブルソート
2と3, 3と4, 4と5は正しくて…
5と1が逆ですね。
• ソートアルゴリズムの一種
• 左右で大小関係が異なれば交換
5432 1
バブルソート
はい、反転しました。
• ソートアルゴリズムの一種
• 左右で大小関係が異なれば交換
1432 5
バブルソート
同様に次は4と1ですね。
• ソートアルゴリズムの一種
• 左右で大小関係が異なれば交換
1432 5
バブルソート
そして3と1。
• ソートアルゴリズムの一種
• 左右で大小関係が異なれば交換
4132 5
バブルソート
最後に2と1ですね。
• ソートアルゴリズムの一種
• 左右で大小関係が異なれば交換
4312 5
バブルソート
これですべての関係が成り立つので
昇順に並べることができましたね。
• ソートアルゴリズムの一種
• 左右で大小関係が異なれば交換
4321 5
バブルソート
多分、バブルソートの疑似言語とC言語は出
ないと信じます…
• ソートアルゴリズムの一種
• 左右で大小関係が異なれば交換
クイックソート
最後にクイックソートですね。
マージソートって範囲外ですよね?
• ソートアルゴリズムの一種
• 本来かなり高速なアルゴリズム
クイックソート
クイックソートは分割統治法といって、
細かい部分に分けて
並び替えを行うアルゴリズムの一種です。
• ソートアルゴリズムの一種
• 本来かなり高速なアルゴリズム
クイックソート
細部では細かい処理になるので
とても高速に動作が可能なわけです。
• ソートアルゴリズムの一種
• 本来かなり高速なアルゴリズム
クイックソート
では疑似言語です。
入力 : 整数列 A1, A2, … An
出力 : 入力列の昇順
• 0 与えられたデータが1つor全部一緒なら終了;
• 1 入力列の中からピボットaを選択する;
• 2 for i ← 1 to n do
• 3 | if Ai <= a then
• 4 | | Ai を列P1に加える;
• 5 | end
• 6 | else
• 7 | | Aiを列P2に加える;
• 8 | end
• 9 end
• 10 P1とP2をそれぞれ整列させる;
• 11 P1の末尾にP2を連結して解とする;
クイックソート
まず注目していきたいのが、こちらの10
P1とP2はそれぞれクイックソートします。
これが分割統治法でよくある再帰ですね。
入力 : 整数列 A1, A2, … An
出力 : 入力列の昇順
• 0 与えられたデータが1つor全部一緒なら終了;
• 1 入力列の中からピボットaを選択する;
• 2 for i ← 1 to n do
• 3 | if Ai <= a then
• 4 | | Ai を列P1に加える;
• 5 | end
• 6 | else
• 7 | | Aiを列P2に加える;
• 8 | end
• 9 end
• 10 P1とP2をそれぞれ整列させる;
• 11 P1の末尾にP2を連結して解とする;
クイックソート
つまり、この関数は内部で自分を呼び出す
わけです。
入力 : 整数列 A1, A2, … An
出力 : 入力列の昇順
• 0 与えられたデータが1つor全部一緒なら終了;
• 1 入力列の中からピボットaを選択する;
• 2 for i ← 1 to n do
• 3 | if Ai <= a then
• 4 | | Ai を列P1に加える;
• 5 | end
• 6 | else
• 7 | | Aiを列P2に加える;
• 8 | end
• 9 end
• 10 P1とP2をそれぞれ整列させる;
• 11 P1の末尾にP2を連結して解とする;
クイックソート
最終的に細部で整列されて、
最終的に解になる!
実にいい仕組みです!
入力 : 整数列 A1, A2, … An
出力 : 入力列の昇順
• 0 与えられたデータが1つor全部一緒なら終了;
• 1 入力列の中からピボットaを選択する;
• 2 for i ← 1 to n do
• 3 | if Ai <= a then
• 4 | | Ai を列P1に加える;
• 5 | end
• 6 | else
• 7 | | Aiを列P2に加える;
• 8 | end
• 9 end
• 10 P1とP2をそれぞれ整列させる;
• 11 P1の末尾にP2を連結して解とする;
クイックソート
再帰になると若干人が変わります…
ごめんなさい…
入力 : 整数列 A1, A2, … An
出力 : 入力列の昇順
• 0 与えられたデータが1つor全部一緒なら終了;
• 1 入力列の中からピボットaを選択する;
• 2 for i ← 1 to n do
• 3 | if Ai <= a then
• 4 | | Ai を列P1に加える;
• 5 | end
• 6 | else
• 7 | | Aiを列P2に加える;
• 8 | end
• 9 end
• 10 P1とP2をそれぞれ整列させる;
• 11 P1の末尾にP2を連結して解とする;
クイックソート
ではまず0を見てみましょう。
これは再帰の終了条件となります。
最終的な処理を止めるのがこの条件です。
入力 : 整数列 A1, A2, … An
出力 : 入力列の昇順
• 0 与えられたデータが1つor全部一緒なら終了;
• 1 入力列の中からピボットaを選択する;
• 2 for i ← 1 to n do
• 3 | if Ai <= a then
• 4 | | Ai を列P1に加える;
• 5 | end
• 6 | else
• 7 | | Aiを列P2に加える;
• 8 | end
• 9 end
• 10 P1とP2をそれぞれ整列させる;
• 11 P1の末尾にP2を連結して解とする;
クイックソート
データが1個、ないしすべて同じ値…
つまりすでに整列されている
ということになります。
入力 : 整数列 A1, A2, … An
出力 : 入力列の昇順
• 0 与えられたデータが1つor全部一緒なら終了;
• 1 入力列の中からピボットaを選択する;
• 2 for i ← 1 to n do
• 3 | if Ai <= a then
• 4 | | Ai を列P1に加える;
• 5 | end
• 6 | else
• 7 | | Aiを列P2に加える;
• 8 | end
• 9 end
• 10 P1とP2をそれぞれ整列させる;
• 11 P1の末尾にP2を連結して解とする;
クイックソート
次にピボットですが
これは選び方が複数あるので後述します。
入力 : 整数列 A1, A2, … An
出力 : 入力列の昇順
• 0 与えられたデータが1つor全部一緒なら終了;
• 1 入力列の中からピボットaを選択する;
• 2 for i ← 1 to n do
• 3 | if Ai <= a then
• 4 | | Ai を列P1に加える;
• 5 | end
• 6 | else
• 7 | | Aiを列P2に加える;
• 8 | end
• 9 end
• 10 P1とP2をそれぞれ整列させる;
• 11 P1の末尾にP2を連結して解とする;
クイックソート
分割統治法のミソとなるのが
この2つに分ける操作です。
入力 : 整数列 A1, A2, … An
出力 : 入力列の昇順
• 0 与えられたデータが1つor全部一緒なら終了;
• 1 入力列の中からピボットaを選択する;
• 2 for i ← 1 to n do
• 3 | if Ai <= a then
• 4 | | Ai を列P1に加える;
• 5 | end
• 6 | else
• 7 | | Aiを列P2に加える;
• 8 | end
• 9 end
• 10 P1とP2をそれぞれ整列させる;
• 11 P1の末尾にP2を連結して解とする;
クイックソート
この時点で、
P1のすべての要素<P2のすべての要素
となりますね。
入力 : 整数列 A1, A2, … An
出力 : 入力列の昇順
• 0 与えられたデータが1つor全部一緒なら終了;
• 1 入力列の中からピボットaを選択する;
• 2 for i ← 1 to n do
• 3 | if Ai <= a then
• 4 | | Ai を列P1に加える;
• 5 | end
• 6 | else
• 7 | | Aiを列P2に加える;
• 8 | end
• 9 end
• 10 P1とP2をそれぞれ整列させる;
• 11 P1の末尾にP2を連結して解とする;
クイックソート
つまり、あとはそれらが整列されていれば
連結させるだけでよくなるのです。
入力 : 整数列 A1, A2, … An
出力 : 入力列の昇順
• 0 与えられたデータが1つor全部一緒なら終了;
• 1 入力列の中からピボットaを選択する;
• 2 for i ← 1 to n do
• 3 | if Ai <= a then
• 4 | | Ai を列P1に加える;
• 5 | end
• 6 | else
• 7 | | Aiを列P2に加える;
• 8 | end
• 9 end
• 10 P1とP2をそれぞれ整列させる;
• 11 P1の末尾にP2を連結して解とする;
クイックソート
それを行うのが、この再帰の部分ですね。
入力 : 整数列 A1, A2, … An
出力 : 入力列の昇順
• 0 与えられたデータが1つor全部一緒なら終了;
• 1 入力列の中からピボットaを選択する;
• 2 for i ← 1 to n do
• 3 | if Ai <= a then
• 4 | | Ai を列P1に加える;
• 5 | end
• 6 | else
• 7 | | Aiを列P2に加える;
• 8 | end
• 9 end
• 10 P1とP2をそれぞれ整列させる;
• 11 P1の末尾にP2を連結して解とする;
クイックソート
C言語のソースコードです。
見づらくてごめんなさい。
void QuickSort(int * p, int n){
int i, a; int p1[100], p2[100]; int *ptr1 = p1, *ptr2 = p2;
if (n == 1) return;
a = p[0];
for (i = 1; i < n; i++){
if (a > p[i]){
a = p[i];
break;
}
else if (a < p[i]) break;
}
if (i == n) return; // breakされない→全部同じ数字
for (i = 0; i < n; i++){ // 教科書のはaの添え字 (1~n) => (0~n-1)
if (p[i] <= a) *ptr1++ = p[i]
else *ptr2++ = p[i];
// 再帰呼び出し (分割した要素のクイックソート)
QuickSort(p1, ptr1 - p1);
QuickSort(p2, ptr2 - p2);
// 連結
for (i = 0; i < ptr1 - p1; i++) *p++ = p1[i];
for (i = 0; i < ptr2 - p2; i++) *p++ = p2[i];
}
クイックソート
まずこれが関数名ですね。
void QuickSort(int * p, int n){
int i, a; int p1[100], p2[100]; int *ptr1 = p1, *ptr2 = p2;
if (n == 1) return;
a = p[0];
for (i = 1; i < n; i++){
if (a > p[i]){
a = p[i];
break;
}
else if (a < p[i]) break;
}
if (i == n) return; // breakされない→全部同じ数字
for (i = 0; i < n; i++){ // 教科書のはaの添え字 (1~n) => (0~n-1)
if (p[i] <= a) *ptr1++ = p[i]
else *ptr2++ = p[i];
// 再帰呼び出し (分割した要素のクイックソート)
QuickSort(p1, ptr1 - p1);
QuickSort(p2, ptr2 - p2);
// 連結
for (i = 0; i < ptr1 - p1; i++) *p++ = p1[i];
for (i = 0; i < ptr2 - p2; i++) *p++ = p2[i];
}
クイックソート
つまり、ここで再帰的に呼ばれます。
void QuickSort(int * p, int n){
int i, a; int p1[100], p2[100]; int *ptr1 = p1, *ptr2 = p2;
if (n == 1) return;
a = p[0];
for (i = 1; i < n; i++){
if (a > p[i]){
a = p[i];
break;
}
else if (a < p[i]) break;
}
if (i == n) return; // breakされない→全部同じ数字
for (i = 0; i < n; i++){ // 教科書のはaの添え字 (1~n) => (0~n-1)
if (p[i] <= a) *ptr1++ = p[i]
else *ptr2++ = p[i];
// 再帰呼び出し (分割した要素のクイックソート)
QuickSort(p1, ptr1 - p1);
QuickSort(p2, ptr2 - p2);
// 連結
for (i = 0; i < ptr1 - p1; i++) *p++ = p1[i];
for (i = 0; i < ptr2 - p2; i++) *p++ = p2[i];
}
クイックソート
次に終了条件がこちらとなります。
void QuickSort(int * p, int n){
int i, a; int p1[100], p2[100]; int *ptr1 = p1, *ptr2 = p2;
if (n == 1) return;
a = p[0];
for (i = 1; i < n; i++){
if (a > p[i]){
a = p[i];
break;
}
else if (a < p[i]) break;
}
if (i == n) return; // breakされない→全部同じ数字
for (i = 0; i < n; i++){ // 教科書のはaの添え字 (1~n) => (0~n-1)
if (p[i] <= a) *ptr1++ = p[i]
else *ptr2++ = p[i];
// 再帰呼び出し (分割した要素のクイックソート)
QuickSort(p1, ptr1 - p1);
QuickSort(p2, ptr2 - p2);
// 連結
for (i = 0; i < ptr1 - p1; i++) *p++ = p1[i];
for (i = 0; i < ptr2 - p2; i++) *p++ = p2[i];
}
クイックソート
まず要素数が1の場合ですね。
void QuickSort(int * p, int n){
int i, a; int p1[100], p2[100]; int *ptr1 = p1, *ptr2 = p2;
if (n == 1) return;
a = p[0];
for (i = 1; i < n; i++){
if (a > p[i]){
a = p[i];
break;
}
else if (a < p[i]) break;
}
if (i == n) return; // breakされない→全部同じ数字
for (i = 0; i < n; i++){ // 教科書のはaの添え字 (1~n) => (0~n-1)
if (p[i] <= a) *ptr1++ = p[i]
else *ptr2++ = p[i];
// 再帰呼び出し (分割した要素のクイックソート)
QuickSort(p1, ptr1 - p1);
QuickSort(p2, ptr2 - p2);
// 連結
for (i = 0; i < ptr1 - p1; i++) *p++ = p1[i];
for (i = 0; i < ptr2 - p2; i++) *p++ = p2[i];
}
クイックソート
次にすべての値が同じときです。
これは配列の先頭から小さい数を
見つけれなかったとき、ということです。
void QuickSort(int * p, int n){
int i, a; int p1[100], p2[100]; int *ptr1 = p1, *ptr2 = p2;
if (n == 1) return;
a = p[0];
for (i = 1; i < n; i++){
if (a > p[i]){
a = p[i];
break;
}
else if (a < p[i]) break;
}
if (i == n) return; // breakされない→全部同じ数字
for (i = 0; i < n; i++){ // 教科書のはaの添え字 (1~n) => (0~n-1)
if (p[i] <= a) *ptr1++ = p[i]
else *ptr2++ = p[i];
// 再帰呼び出し (分割した要素のクイックソート)
QuickSort(p1, ptr1 - p1);
QuickSort(p2, ptr2 - p2);
// 連結
for (i = 0; i < ptr1 - p1; i++) *p++ = p1[i];
for (i = 0; i < ptr2 - p2; i++) *p++ = p2[i];
}
クイックソート
ということは、ここが配列の先頭から
小さい数を見つける部分ですね。
void QuickSort(int * p, int n){
int i, a; int p1[100], p2[100]; int *ptr1 = p1, *ptr2 = p2;
if (n == 1) return;
a = p[0];
for (i = 1; i < n; i++){
if (a > p[i]){
a = p[i];
break;
}
else if (a < p[i]) break;
}
if (i == n) return; // breakされない→全部同じ数字
for (i = 0; i < n; i++){ // 教科書のはaの添え字 (1~n) => (0~n-1)
if (p[i] <= a) *ptr1++ = p[i]
else *ptr2++ = p[i];
// 再帰呼び出し (分割した要素のクイックソート)
QuickSort(p1, ptr1 - p1);
QuickSort(p2, ptr2 - p2);
// 連結
for (i = 0; i < ptr1 - p1; i++) *p++ = p1[i];
for (i = 0; i < ptr2 - p2; i++) *p++ = p2[i];
}
クイックソート
最後に連結ですね。
void QuickSort(int * p, int n){
int i, a; int p1[100], p2[100]; int *ptr1 = p1, *ptr2 = p2;
if (n == 1) return;
a = p[0];
for (i = 1; i < n; i++){
if (a > p[i]){
a = p[i];
break;
}
else if (a < p[i]) break;
}
if (i == n) return; // breakされない→全部同じ数字
for (i = 0; i < n; i++){ // 教科書のはaの添え字 (1~n) => (0~n-1)
if (p[i] <= a) *ptr1++ = p[i]
else *ptr2++ = p[i];
// 再帰呼び出し (分割した要素のクイックソート)
QuickSort(p1, ptr1 - p1);
QuickSort(p2, ptr2 - p2);
// 連結
for (i = 0; i < ptr1 - p1; i++) *p++ = p1[i];
for (i = 0; i < ptr2 - p2; i++) *p++ = p2[i];
}
クイックソート
これだけの仕組みで
クイックソートは成り立っています。
void QuickSort(int * p, int n){
int i, a; int p1[100], p2[100]; int *ptr1 = p1, *ptr2 = p2;
if (n == 1) return;
a = p[0];
for (i = 1; i < n; i++){
if (a > p[i]){
a = p[i];
break;
}
else if (a < p[i]) break;
}
if (i == n) return; // breakされない→全部同じ数字
for (i = 0; i < n; i++){ // 教科書のはaの添え字 (1~n) => (0~n-1)
if (p[i] <= a) *ptr1++ = p[i]
else *ptr2++ = p[i];
// 再帰呼び出し (分割した要素のクイックソート)
QuickSort(p1, ptr1 - p1);
QuickSort(p2, ptr2 - p2);
// 連結
for (i = 0; i < ptr1 - p1; i++) *p++ = p1[i];
for (i = 0; i < ptr2 - p2; i++) *p++ = p2[i];
}
クイックソート
ということで後述のピボットの選択方法です。
• ピボットの選択の仕方
→ 左端 (終わらない)
→ ランダム (そのうち終わる)
→ 今回の手法 (終了する)
左端より小さな
一番初めに見つけた数
クイックソート
左端ですが、
これは左端が最大値だった場合、すべてが
P1に振り分けられるため終わりません。
• ピボットの選択の仕方
→ 左端 (終わらない)
→ ランダム (そのうち終わる)
→ 今回の手法 (終了する)
左端より小さな
一番初めに見つけた数
クイックソート
ならばランダムに選択すれば、
そのうち終わります。
これは割と使われることもあります。
• ピボットの選択の仕方
→ 左端 (終わらない)
→ ランダム (そのうち終わる)
→ 今回の手法 (終了する)
左端より小さな
一番初めに見つけた数
クイックソート
最後に今回の手法となります。
これはきちんと終了しますね。
• ピボットの選択の仕方
→ 左端 (終わらない)
→ ランダム (そのうち終わる)
→ 今回の手法 (終了する)
左端より小さな
一番初めに見つけた数
クイックソート
それでは、
クイックソートの動作を確認してみましょう。
5134 2
クイックソート
ピボットは4より小さい3に決定します。
5134 2
クイックソート
そしてピボットの3以下のP1と
3より大きいP2に分けます。
5134 2
513 2 4
クイックソート
同様に左側では1が、
右側では4がピボットに選ばれます。
5134 2
513 2 4
クイックソート
するとまた同様に分かれますね。
5134 2
513 2 4
1 3 2 54
クイックソート
3と2に関してはまだ作業が続きますね。
2がピボットになるので…
5134 2
513 2 4
1 3 2 54
クイックソート
最後に1つずつになるので、
あとは連結すれば整列できます。
5134 2
513 2 4
1 3 2
32
54
クイックソート
まず2と3を連結します。
1
32
542 3
クイックソート
次は1~3、4~5を連結しますね。
1
32
542 3
5421 3
クイックソート
最後はすべてを連結して、完成です。
1
32
542 3
5421 3
4321 5
とりあえずここまで?
以上で、各アルゴリズムの解説となります。
とりあえずここまで?
以降、
暗記科目で出そうなものを挙げますね。
アルゴリズムの定義とは
• 問題を解くための手順
問題 → 質問 問題例集合
アルゴリズムは問題を解くための手順です。
アルゴリズムの定義とは
• 問題を解くための手順
問題 → 質問 問題例集合
問題は質問と問題列集合からなります。
問題とは
問題は得られた答えが正しいか否か一意に
判定できる文となります。
問題とは
例えば「ある数Xは素数である」
というのが問題ですね。
問題例集合とは
問題例集合はそのアルゴリズムの入力を具
体的に規定したものです。
例えばある数xは整数…のような感じです。
正しいアルゴリズムとは
正しいアルゴリズムは
「必ず停止して、正しい答えが得られる」
という条件が必要になります。
正しい問題
また、正しい問題と
正しくない問題があります。
正しい問題
正しい問題は、
答えをきちんと選ぶことができる問題です。
正しい問題
例えば、1÷11の小数第4位は何か?
という問題なら答えることができますね。
正しくない問題
逆に正しくない問題は、
問題の定義が曖昧な問題です。
正しくない問題
世界で一番強い生き物は何か?
という問題は答えることができませんね。
さまざまなアルゴリズム
• 万能でないアルゴリズム
迷路の左手法 → 時々解けない
• モンテカルロ法
高い確率で高速に正しい答えを出す
→ 正しくない場合もある
• ラスベガス法
高い確率で高速に正しい答えを出す
→ 遅い場合もある
まぁそんなこんなで、
万能でないアルゴリズムや確率を利用する
アルゴリズムなどいろいろあります。
暗記嫌い
暗記の方は各自ノートの方を見てください。
お願いします。
以上
以上簡単ですが、
アルゴリズムのお勉強となります。
教科書
• アルゴリズムとデータ構造 数理工学社 藤田 聡 2013/3/10
教科書のため、ところどころ引用になってる場所があります
立ち絵素材
• 臼井の会様 http://usui.moo.jp/frame2.html
ご視聴ありがとうございました。
頑張ってくださいね。

More Related Content

Viewers also liked

upload test slide
upload test slideupload test slide
upload test slidehixi365
 
アルゴリズムのイメージを擬人化する
アルゴリズムのイメージを擬人化するアルゴリズムのイメージを擬人化する
アルゴリズムのイメージを擬人化するAtCoder Inc.
 
2011年10月7日
2011年10月7日2011年10月7日
2011年10月7日nukaemon
 
その文字列検索、std::string::findだけで大丈夫ですか?【Sapporo.cpp 第8回勉強会(2014.12.27)】
その文字列検索、std::string::findだけで大丈夫ですか?【Sapporo.cpp 第8回勉強会(2014.12.27)】その文字列検索、std::string::findだけで大丈夫ですか?【Sapporo.cpp 第8回勉強会(2014.12.27)】
その文字列検索、std::string::findだけで大丈夫ですか?【Sapporo.cpp 第8回勉強会(2014.12.27)】Hiro H.
 
角錐や円錐が、角柱や円柱の体積の3分の1であることを積分・極限抜きで証明してみる
角錐や円錐が、角柱や円柱の体積の3分の1であることを積分・極限抜きで証明してみる角錐や円錐が、角柱や円柱の体積の3分の1であることを積分・極限抜きで証明してみる
角錐や円錐が、角柱や円柱の体積の3分の1であることを積分・極限抜きで証明してみるHiro H.
 
単語・パラグラフの分散表現を用いたTwitterからの日本語評判情報抽出
単語・パラグラフの分散表現を用いたTwitterからの日本語評判情報抽出単語・パラグラフの分散表現を用いたTwitterからの日本語評判情報抽出
単語・パラグラフの分散表現を用いたTwitterからの日本語評判情報抽出奈良先端大 情報科学研究科
 
超音波通信という怪しい技術 In html5minutes 7 #tritonjs
超音波通信という怪しい技術 In html5minutes 7 #tritonjs超音波通信という怪しい技術 In html5minutes 7 #tritonjs
超音波通信という怪しい技術 In html5minutes 7 #tritonjsK Kinzal
 
文字列検索のいろいろ
文字列検索のいろいろ文字列検索のいろいろ
文字列検索のいろいろKazuma Mikami
 
競技プログラミングでの線型方程式系
競技プログラミングでの線型方程式系競技プログラミングでの線型方程式系
競技プログラミングでの線型方程式系tmaehara
 
rsyncで差分バックアップしようぜ!
rsyncで差分バックアップしようぜ!rsyncで差分バックアップしようぜ!
rsyncで差分バックアップしようぜ!Hiro H.
 
エンジニア向け夏期特別講座 〜 Red Hat OpenStack徹底解説! 第一部 OpenStack入門
エンジニア向け夏期特別講座 〜 Red Hat OpenStack徹底解説! 第一部 OpenStack入門エンジニア向け夏期特別講座 〜 Red Hat OpenStack徹底解説! 第一部 OpenStack入門
エンジニア向け夏期特別講座 〜 Red Hat OpenStack徹底解説! 第一部 OpenStack入門Etsuji Nakai
 
iPhoneのBluetoothについての知見まとめ
iPhoneのBluetoothについての知見まとめiPhoneのBluetoothについての知見まとめ
iPhoneのBluetoothについての知見まとめShuichi Tsutsumi
 
名古屋市営地下鉄最小距離完乗
名古屋市営地下鉄最小距離完乗名古屋市営地下鉄最小距離完乗
名古屋市営地下鉄最小距離完乗Hiro H.
 
Python & PyConJP 2014 Report
Python & PyConJP 2014 ReportPython & PyConJP 2014 Report
Python & PyConJP 2014 Reportgree_tech
 
実践・最強最速のアルゴリズム勉強会 第四回講義資料(ワークスアプリケーションズ & AtCoder)
実践・最強最速のアルゴリズム勉強会 第四回講義資料(ワークスアプリケーションズ & AtCoder)実践・最強最速のアルゴリズム勉強会 第四回講義資料(ワークスアプリケーションズ & AtCoder)
実践・最強最速のアルゴリズム勉強会 第四回講義資料(ワークスアプリケーションズ & AtCoder)AtCoder Inc.
 
Pythonデータ分析 第4回勉強会資料 12章
Pythonデータ分析 第4回勉強会資料 12章Pythonデータ分析 第4回勉強会資料 12章
Pythonデータ分析 第4回勉強会資料 12章Makoto Kawano
 
Python勉強会1-はじめに
Python勉強会1-はじめにPython勉強会1-はじめに
Python勉強会1-はじめに理 小林
 

Viewers also liked (20)

upload test slide
upload test slideupload test slide
upload test slide
 
アルゴリズムのイメージを擬人化する
アルゴリズムのイメージを擬人化するアルゴリズムのイメージを擬人化する
アルゴリズムのイメージを擬人化する
 
2011年10月7日
2011年10月7日2011年10月7日
2011年10月7日
 
アルゴリズムとデータ構造(初歩)
アルゴリズムとデータ構造(初歩)アルゴリズムとデータ構造(初歩)
アルゴリズムとデータ構造(初歩)
 
その文字列検索、std::string::findだけで大丈夫ですか?【Sapporo.cpp 第8回勉強会(2014.12.27)】
その文字列検索、std::string::findだけで大丈夫ですか?【Sapporo.cpp 第8回勉強会(2014.12.27)】その文字列検索、std::string::findだけで大丈夫ですか?【Sapporo.cpp 第8回勉強会(2014.12.27)】
その文字列検索、std::string::findだけで大丈夫ですか?【Sapporo.cpp 第8回勉強会(2014.12.27)】
 
Kancolle
KancolleKancolle
Kancolle
 
角錐や円錐が、角柱や円柱の体積の3分の1であることを積分・極限抜きで証明してみる
角錐や円錐が、角柱や円柱の体積の3分の1であることを積分・極限抜きで証明してみる角錐や円錐が、角柱や円柱の体積の3分の1であることを積分・極限抜きで証明してみる
角錐や円錐が、角柱や円柱の体積の3分の1であることを積分・極限抜きで証明してみる
 
単語・パラグラフの分散表現を用いたTwitterからの日本語評判情報抽出
単語・パラグラフの分散表現を用いたTwitterからの日本語評判情報抽出単語・パラグラフの分散表現を用いたTwitterからの日本語評判情報抽出
単語・パラグラフの分散表現を用いたTwitterからの日本語評判情報抽出
 
超音波通信という怪しい技術 In html5minutes 7 #tritonjs
超音波通信という怪しい技術 In html5minutes 7 #tritonjs超音波通信という怪しい技術 In html5minutes 7 #tritonjs
超音波通信という怪しい技術 In html5minutes 7 #tritonjs
 
二分探索をはじめからていねいに
二分探索をはじめからていねいに二分探索をはじめからていねいに
二分探索をはじめからていねいに
 
文字列検索のいろいろ
文字列検索のいろいろ文字列検索のいろいろ
文字列検索のいろいろ
 
競技プログラミングでの線型方程式系
競技プログラミングでの線型方程式系競技プログラミングでの線型方程式系
競技プログラミングでの線型方程式系
 
rsyncで差分バックアップしようぜ!
rsyncで差分バックアップしようぜ!rsyncで差分バックアップしようぜ!
rsyncで差分バックアップしようぜ!
 
エンジニア向け夏期特別講座 〜 Red Hat OpenStack徹底解説! 第一部 OpenStack入門
エンジニア向け夏期特別講座 〜 Red Hat OpenStack徹底解説! 第一部 OpenStack入門エンジニア向け夏期特別講座 〜 Red Hat OpenStack徹底解説! 第一部 OpenStack入門
エンジニア向け夏期特別講座 〜 Red Hat OpenStack徹底解説! 第一部 OpenStack入門
 
iPhoneのBluetoothについての知見まとめ
iPhoneのBluetoothについての知見まとめiPhoneのBluetoothについての知見まとめ
iPhoneのBluetoothについての知見まとめ
 
名古屋市営地下鉄最小距離完乗
名古屋市営地下鉄最小距離完乗名古屋市営地下鉄最小距離完乗
名古屋市営地下鉄最小距離完乗
 
Python & PyConJP 2014 Report
Python & PyConJP 2014 ReportPython & PyConJP 2014 Report
Python & PyConJP 2014 Report
 
実践・最強最速のアルゴリズム勉強会 第四回講義資料(ワークスアプリケーションズ & AtCoder)
実践・最強最速のアルゴリズム勉強会 第四回講義資料(ワークスアプリケーションズ & AtCoder)実践・最強最速のアルゴリズム勉強会 第四回講義資料(ワークスアプリケーションズ & AtCoder)
実践・最強最速のアルゴリズム勉強会 第四回講義資料(ワークスアプリケーションズ & AtCoder)
 
Pythonデータ分析 第4回勉強会資料 12章
Pythonデータ分析 第4回勉強会資料 12章Pythonデータ分析 第4回勉強会資料 12章
Pythonデータ分析 第4回勉強会資料 12章
 
Python勉強会1-はじめに
Python勉強会1-はじめにPython勉強会1-はじめに
Python勉強会1-はじめに
 

Similar to アルゴリズムのお勉強 アルゴリズムとデータ構造 [素数・文字列探索・簡単なソート]

Haskell勉強会2 in ie
Haskell勉強会2 in ieHaskell勉強会2 in ie
Haskell勉強会2 in iemaeken2010
 
純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門Kimikazu Kato
 
AtCoder Beginner Contest 009 解説
AtCoder Beginner Contest 009 解説AtCoder Beginner Contest 009 解説
AtCoder Beginner Contest 009 解説AtCoder Inc.
 
Math tutorial public
Math tutorial publicMath tutorial public
Math tutorial publicKenta Oono
 
Learning to automatically solve algebra word problems
Learning to automatically solve algebra word problemsLearning to automatically solve algebra word problems
Learning to automatically solve algebra word problemsNaoaki Okazaki
 
コーパス事例の観察に基づく日本語清掃表現の記述的一般化,並びに自作例による妥当性の検証
コーパス事例の観察に基づく日本語清掃表現の記述的一般化,並びに自作例による妥当性の検証コーパス事例の観察に基づく日本語清掃表現の記述的一般化,並びに自作例による妥当性の検証
コーパス事例の観察に基づく日本語清掃表現の記述的一般化,並びに自作例による妥当性の検証Kow Kuroda
 
LINQ を使ったナンプレの解法を作ったお話
LINQ を使ったナンプレの解法を作ったお話LINQ を使ったナンプレの解法を作ったお話
LINQ を使ったナンプレの解法を作ったお話Fumihito Yokoyama
 
JavaScriptの正規表現
JavaScriptの正規表現JavaScriptの正規表現
JavaScriptの正規表現yaju88
 

Similar to アルゴリズムのお勉強 アルゴリズムとデータ構造 [素数・文字列探索・簡単なソート] (14)

詳説word2vec
詳説word2vec詳説word2vec
詳説word2vec
 
Haskell勉強会2 in ie
Haskell勉強会2 in ieHaskell勉強会2 in ie
Haskell勉強会2 in ie
 
純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門
 
Abc009
Abc009Abc009
Abc009
 
AtCoder Beginner Contest 009 解説
AtCoder Beginner Contest 009 解説AtCoder Beginner Contest 009 解説
AtCoder Beginner Contest 009 解説
 
Math tutorial public
Math tutorial publicMath tutorial public
Math tutorial public
 
Learning to automatically solve algebra word problems
Learning to automatically solve algebra word problemsLearning to automatically solve algebra word problems
Learning to automatically solve algebra word problems
 
コーパス事例の観察に基づく日本語清掃表現の記述的一般化,並びに自作例による妥当性の検証
コーパス事例の観察に基づく日本語清掃表現の記述的一般化,並びに自作例による妥当性の検証コーパス事例の観察に基づく日本語清掃表現の記述的一般化,並びに自作例による妥当性の検証
コーパス事例の観察に基づく日本語清掃表現の記述的一般化,並びに自作例による妥当性の検証
 
Ruby講座一回目
Ruby講座一回目Ruby講座一回目
Ruby講座一回目
 
Ruby講座一回目
Ruby講座一回目Ruby講座一回目
Ruby講座一回目
 
LINQ を使ったナンプレの解法を作ったお話
LINQ を使ったナンプレの解法を作ったお話LINQ を使ったナンプレの解法を作ったお話
LINQ を使ったナンプレの解法を作ったお話
 
Python opt
Python optPython opt
Python opt
 
WUPC2012
WUPC2012WUPC2012
WUPC2012
 
JavaScriptの正規表現
JavaScriptの正規表現JavaScriptの正規表現
JavaScriptの正規表現
 

Recently uploaded

ゲーム理論 BASIC 演習105 -n人囚人のジレンマモデル- #ゲーム理論 #gametheory #数学
ゲーム理論 BASIC 演習105 -n人囚人のジレンマモデル- #ゲーム理論 #gametheory #数学ゲーム理論 BASIC 演習105 -n人囚人のジレンマモデル- #ゲーム理論 #gametheory #数学
ゲーム理論 BASIC 演習105 -n人囚人のジレンマモデル- #ゲーム理論 #gametheory #数学ssusere0a682
 
リアル戦国探究in米沢 当日講座2スライド(スタッフ共有用)『人を致すも人に致されず』についてのスライド
リアル戦国探究in米沢 当日講座2スライド(スタッフ共有用)『人を致すも人に致されず』についてのスライドリアル戦国探究in米沢 当日講座2スライド(スタッフ共有用)『人を致すも人に致されず』についてのスライド
リアル戦国探究in米沢 当日講座2スライド(スタッフ共有用)『人を致すも人に致されず』についてのスライドKen Fukui
 
リアル戦国探究in米沢 事前講座1スライド(スタッフ共有用)『川中島の謎』についてのスライド
リアル戦国探究in米沢 事前講座1スライド(スタッフ共有用)『川中島の謎』についてのスライドリアル戦国探究in米沢 事前講座1スライド(スタッフ共有用)『川中島の謎』についてのスライド
リアル戦国探究in米沢 事前講座1スライド(スタッフ共有用)『川中島の謎』についてのスライドKen Fukui
 
TokyoTechGraduateExaminationPresentation
TokyoTechGraduateExaminationPresentationTokyoTechGraduateExaminationPresentation
TokyoTechGraduateExaminationPresentationYukiTerazawa
 
リアル戦国探究in米沢 当日講座3スライド(スタッフ共有用)『糧は三度はさいせず』についてのスライド
リアル戦国探究in米沢 当日講座3スライド(スタッフ共有用)『糧は三度はさいせず』についてのスライドリアル戦国探究in米沢 当日講座3スライド(スタッフ共有用)『糧は三度はさいせず』についてのスライド
リアル戦国探究in米沢 当日講座3スライド(スタッフ共有用)『糧は三度はさいせず』についてのスライドKen Fukui
 
TEAMIN Service overview for customer_20240422.pdf
TEAMIN Service overview for customer_20240422.pdfTEAMIN Service overview for customer_20240422.pdf
TEAMIN Service overview for customer_20240422.pdfyukisuga3
 
UniProject Workshop Make a Discord Bot with JavaScript
UniProject Workshop Make a Discord Bot with JavaScriptUniProject Workshop Make a Discord Bot with JavaScript
UniProject Workshop Make a Discord Bot with JavaScriptyuitoakatsukijp
 
リアル戦国探究in米沢 事前講座2スライド(スタッフ共有用)『両雄の強さの秘密』についてのスライド
リアル戦国探究in米沢 事前講座2スライド(スタッフ共有用)『両雄の強さの秘密』についてのスライドリアル戦国探究in米沢 事前講座2スライド(スタッフ共有用)『両雄の強さの秘密』についてのスライド
リアル戦国探究in米沢 事前講座2スライド(スタッフ共有用)『両雄の強さの秘密』についてのスライドKen Fukui
 
リアル戦国探究in米沢 当日講座1(スタッフ共有用)『兵は詐をもって立つ』についてのスライド
リアル戦国探究in米沢 当日講座1(スタッフ共有用)『兵は詐をもって立つ』についてのスライドリアル戦国探究in米沢 当日講座1(スタッフ共有用)『兵は詐をもって立つ』についてのスライド
リアル戦国探究in米沢 当日講座1(スタッフ共有用)『兵は詐をもって立つ』についてのスライドKen Fukui
 
The_Five_Books_Overview_Presentation_2024
The_Five_Books_Overview_Presentation_2024The_Five_Books_Overview_Presentation_2024
The_Five_Books_Overview_Presentation_2024koheioishi1
 

Recently uploaded (10)

ゲーム理論 BASIC 演習105 -n人囚人のジレンマモデル- #ゲーム理論 #gametheory #数学
ゲーム理論 BASIC 演習105 -n人囚人のジレンマモデル- #ゲーム理論 #gametheory #数学ゲーム理論 BASIC 演習105 -n人囚人のジレンマモデル- #ゲーム理論 #gametheory #数学
ゲーム理論 BASIC 演習105 -n人囚人のジレンマモデル- #ゲーム理論 #gametheory #数学
 
リアル戦国探究in米沢 当日講座2スライド(スタッフ共有用)『人を致すも人に致されず』についてのスライド
リアル戦国探究in米沢 当日講座2スライド(スタッフ共有用)『人を致すも人に致されず』についてのスライドリアル戦国探究in米沢 当日講座2スライド(スタッフ共有用)『人を致すも人に致されず』についてのスライド
リアル戦国探究in米沢 当日講座2スライド(スタッフ共有用)『人を致すも人に致されず』についてのスライド
 
リアル戦国探究in米沢 事前講座1スライド(スタッフ共有用)『川中島の謎』についてのスライド
リアル戦国探究in米沢 事前講座1スライド(スタッフ共有用)『川中島の謎』についてのスライドリアル戦国探究in米沢 事前講座1スライド(スタッフ共有用)『川中島の謎』についてのスライド
リアル戦国探究in米沢 事前講座1スライド(スタッフ共有用)『川中島の謎』についてのスライド
 
TokyoTechGraduateExaminationPresentation
TokyoTechGraduateExaminationPresentationTokyoTechGraduateExaminationPresentation
TokyoTechGraduateExaminationPresentation
 
リアル戦国探究in米沢 当日講座3スライド(スタッフ共有用)『糧は三度はさいせず』についてのスライド
リアル戦国探究in米沢 当日講座3スライド(スタッフ共有用)『糧は三度はさいせず』についてのスライドリアル戦国探究in米沢 当日講座3スライド(スタッフ共有用)『糧は三度はさいせず』についてのスライド
リアル戦国探究in米沢 当日講座3スライド(スタッフ共有用)『糧は三度はさいせず』についてのスライド
 
TEAMIN Service overview for customer_20240422.pdf
TEAMIN Service overview for customer_20240422.pdfTEAMIN Service overview for customer_20240422.pdf
TEAMIN Service overview for customer_20240422.pdf
 
UniProject Workshop Make a Discord Bot with JavaScript
UniProject Workshop Make a Discord Bot with JavaScriptUniProject Workshop Make a Discord Bot with JavaScript
UniProject Workshop Make a Discord Bot with JavaScript
 
リアル戦国探究in米沢 事前講座2スライド(スタッフ共有用)『両雄の強さの秘密』についてのスライド
リアル戦国探究in米沢 事前講座2スライド(スタッフ共有用)『両雄の強さの秘密』についてのスライドリアル戦国探究in米沢 事前講座2スライド(スタッフ共有用)『両雄の強さの秘密』についてのスライド
リアル戦国探究in米沢 事前講座2スライド(スタッフ共有用)『両雄の強さの秘密』についてのスライド
 
リアル戦国探究in米沢 当日講座1(スタッフ共有用)『兵は詐をもって立つ』についてのスライド
リアル戦国探究in米沢 当日講座1(スタッフ共有用)『兵は詐をもって立つ』についてのスライドリアル戦国探究in米沢 当日講座1(スタッフ共有用)『兵は詐をもって立つ』についてのスライド
リアル戦国探究in米沢 当日講座1(スタッフ共有用)『兵は詐をもって立つ』についてのスライド
 
The_Five_Books_Overview_Presentation_2024
The_Five_Books_Overview_Presentation_2024The_Five_Books_Overview_Presentation_2024
The_Five_Books_Overview_Presentation_2024
 

アルゴリズムのお勉強 アルゴリズムとデータ構造 [素数・文字列探索・簡単なソート]