遞迴

遞迴是什麼?

  • 一種函式
  • 自己呼叫自己

聽起來很抽象?

舉例

階乘

\(n! = 1 * 2 * 3 ... * (n - 1) * n\)

定義函式\(f(n)\)為n!的值

舉例

\(n! = n * (n - 1)!\)

 

用遞迴表示\(f(n)\)

\(f(n) = f(n - 1) * n\)

\(f(3) = f(2) * 3\)

\(f(2) = f(1) * 2\)

\(f(1) = f(0) * 1\)

\(f(0) = f(-1) * 0\)

......\(\infty\)

寫出來看看

什麼時候結束?

遞迴終止條件

設結束條件

定f(1) = 1

\(f(3) = f(2) * 3\) = 6

\(f(2) = f(1) * 2\) = 2

\(f(1) = 1\)

#include<bits/stdc++.h>
using namespace std;
int f(int n){
	if(n == 1)
    	return 1;
	return f(n - 1);
}
int main(){
	int n;
    cin >> n;
    cout << f(n) << '\n';
}

試試看吧

e156

費氏數列

  • 1, 1, 2, 3, 5, 8, 13, 21, 34...
  • 第n項是前兩項和
  • \(f(1) = 1, f(2) = 1\)
  • \(f(n) = f(n - 1) + f(n - 2)\)

範例測資

輸入:5  輸出:5

輸入:9  輸出:34

#include<iostream>
using namespace std;
int f(int n) {
	if (n == 1)
		return 1;
	if (n == 2)
		return 1;
	return f(n - 1) + f(n - 2);
}
int main() {
	int x;
	cin >> x;
	cout << f(x) << '\n';
}

河內塔

有a, b, c三根桿子,一開始有N個盤子由大到小往上疊,問最少要花多少步才能把所有盤子從a桿子移到c桿子。

#include<iostream>
using namespace std;
int f(int n) {
	if (n == 1)
		return 1;
	return f(n - 1) * 2 + 1;
}
int main() {
	int x;
	cin >> x;
	cout << f(x) << '\n';
}

實際應用

1~n的所有排列

a524

快速冪

歐基里德算法

aka 輾轉相除法

遞迴枚舉

給一個有長度為n的整數陣列a,計算其中有多少種子集的和等於k。

遞迴枚舉

可以把每一個數字分為拿和不拿,透過遞迴跑過每個可能的狀況。

#include<iostream>
using namespace std;
int n, k, ans = 0, a[30];
void f(int i, int sum = 0) {
	if (i == n) {
		if (sum == k)
			ans++;
		return;
	}
	f(i + 1, sum + a[i]);
	f(i + 1, sum);
}
int main() {
	cin >> n >> k;
	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}
	f(0);
	cout << ans << '\n';
}

遞迴

By scottchou

遞迴

  • 246