i : 0, 1, 2, 3, 4, 5, 6, 7
F : 0, 1, 1, 2, 3, 5, 8, 13
fib(n)
を定義します.fn fib(n: usize) -> usize {
match n {
0 => 0, // n が 0 の場合
1 => 1, // n が 1 の場合
n => fib(n - 1) + fib(n - 2), // n が 0, 1 以外の場合
}
}
fn fib(n: usize) -> usize {
match n {
0 => 0,
1 => 1,
n => fib(n - 1) + fib(n - 2),
}
}
for n in 0..=7 {
println!("fib({}) = {}", n, fib(n));
}
fib(5)
を例に計算を追跡します.fib(5) = fib(4) + fib(3) ... (1)
= fib(3) + fib(2) + fib(3) ... (2)
= fib(2) + fib(1) + fib(2) + fib(3) ... (3)
= fib(1) + fib(0) + fib(1) + fib(2) + fib(3) ... (4)
= fib(1) + fib(0) + fib(1) + fib(1) + fib(0) + fib(3) ... (5)
= fib(1) + fib(0) + fib(1) + fib(1) + fib(0) + fib(2) + fib(1) ... (6)
= fib(1) + fib(0) + fib(1) + fib(1) + fib(0) + fib(1) + fib(0) + fib(1) ... (7)
= 1 + 0 + 1 + 1 + 0 + 1 + 0 + 1 = 5
fib(0), fib(1)
になるまでひたすら展開しています.fib(3) + fib(2) + fib(3) = fib(3) * 2 + fib(2)
的なことができれば, (5) から (7) における 2回目の fib(3) を展開する必要がなくなります.fib(n)
が呼ばれた回数をv[n]
に記録する配列v
を用意し, fib(5)
の場合で確認する.fn fib(n: usize, v: &mut Vec<u32>) -> usize {
v[n] += 1;
match n {
0 => 0,
1 => 1,
n => fib(n - 1, v) + fib(n - 2, v),
}
}
let mut v = vec![0; 8];
fib(5, &mut v);
for n in 0..=5 {
println!("fib({}) was called {} times.", n, v[n]);
}
fib(n) = fib(n - 1) + fib(n - 2)
という風に, 各 の計算が2つに分裂します.
そして は になるまで ずつ減少していくので, 倍, 倍, 倍, ..., を 回, 即ち です.fib(5)
を計算してみる.
恐らくこんな感じで計算する.fib(0) = 0, fib(1) = 1
fib(2) = fib(1) + fib(0) = 1 + 0 = 1
fib(3) = fib(2) + fib(1) = 1 + 1 = 2
fib(4) = fib(3) + fib(2) = 2 + 1 = 3
fib(5) = fib(4) + fib(3) = 3 + 2 = 5
fib(n) = 0, 1
という数値に落ち着く. 逆に言えば, の間はひたすら展開する.None
として扱うため, None
で初期化します.-1
(フィボナッチ数列の定義から, 負の値をとることがない)bool
型配列を別に用意
などの方法もあります.fn fib(n: usize, memo: &mut Vec<Option<usize>>) -> usize {
// memo されていない場合, memo する.
if memo[n].is_none() {
let x = fib(n - 1, memo) + fib(n - 2, memo);
memo[n] = Some(x);
}
// 上の処理のおかげで, memo[n] はすでにメモされている.
memo[n].unwrap()
}
let mut memo = vec![None; 8];
memo[0] = Some(0);
memo[1] = Some(1);
for n in 0..=7 {
println!("fib({}) = {}", n, fib(n, &mut memo));
}
fib(n)
を計算した回数)を調べます.fn fib(n: usize, memo: &mut Vec<Option<usize>>, v: &mut Vec<u32>) -> usize {
if memo[n].is_none() {
v[n] += 1;
let x = fib(n - 1, memo, v) + fib(n - 2, memo, v);
memo[n] = Some(x);
}
memo[n].unwrap()
}
let mut memo = vec![None; 8];
memo[0] = Some(0);
memo[1] = Some(1);
let mut v = vec![0; 8];
fib(5, &mut memo, &mut v);
for n in 0..=5 {
println!("fib({}) was called {} times.", n, v[n]);
}
fib(n) | 0 | 1 | 2 | 3 | 4 | 5 |
---|---|---|---|---|---|---|
愚直 | 3 | 5 | 3 | 2 | 1 | 1 |
メモ | 0 | 0 | 1 | 1 | 1 | 1 |