---
# System prepended metadata

title: 台北康橋G8A 11/6 遞迴 Recursion

---

# 台北康橋G8A 11/6 遞迴 Recursion

## 函式複習
*
1. void (無回傳值)
```
void print(int a[], int n) {
    for(int i=0;i<n;++i)
        cout << a[i] << endl;
}

int main() {
    int a[] = {1, 2, 3, 4, 5};
    print(a, 5);
}
```
2. int (回傳值為整數)
```
void print(int a) {
    cout << a << endl;
}

int square(int a) {
    return a*a;
}

int main() {
    int b = 10;
    // b = square(b);
    print(square(b));
}
```

## 費氏數列 (Fibonaccii Sequence)
$f_{n} = f_{n-1}+f_{n-2}, f_{0}=1, f_{1}=1$
$f(n)=f(n-1)+f(n-2)$
Initial states are important
```
int fibonaccii(int n) {
    if(n == 0 || n == 1)
        return 1;
    return fibonaccii(n-1) + fibonacci(n-2);
}

int main() {
    int n;
    cin >> n;
    cout << fibonaccii(n) << endl;
}
```

## 遞迴樹 (Recursion Tree)

## 階乘 (Factorial)

$5!=5\times4\times3\times2\times1=120$
Initial state: $0!=1$
Recursion: $f(n)=?\times f(n-1)$
$n\times (n-1)\times (n-2)\times ...\times 1=?\times(n-1)\times(n-2)\times...\times 1$
```
int factorial(int n) {
    .......
}

int main() {
    int x;
    cin >> x;
    cout << factorial(x) << endl;
}
```

## 排列 (Permutation)

窮舉所有排列組合，如果有n個人排隊，總共就有$n!$種排法。
（用迴圈寫非常複雜）
```
int main() {
	int chosen[4] = {0};
	int queue[4] = {0};
	for(int i=1;i<=3;++i) {
		chosen[i] = 1;
		queue[1] = i;
		for(int j=1;j<=3;++j) {
			if(chosen[j] == 1)
				continue;
			chosen[j] = 1;
			queue[2] = j;
			for(int k=1;k<=3;++k) {
				if(chosen[k] == 1)
					continue;
				chosen[k] = 1;
				queue[3] = k;
				for(int a=1;a<=3;++a) {
					cout << queue[a] << " ";
				}
				cout << endl;
				chosen[k] = 0;
			}
			chosen[j] = 0;
		}
		chosen[i] = 0;
	}
}

```
用recursion實做permutation
```
// chosen[i] == 1 -> i 被選過了
// chosen[i] == 0 -> i 沒被選過了
int chosen[] = {};
int queue[] = {};

int permutation(int n, int x) {
    // n個人排隊，已經排好x個
    if(n == x) {
        for(int i=1;i<=n;++i)
            cout << queue[i] << " ";
        cout << endl;
        return;
    }
    else {
        for(int i=1;i<=n;++i) {
            if(chosen[i] != 1) {
                queue[x+1] = i;
                chosen[i] = 1;
                permutation(n, x+1);
                chosen[i] = 0;
            }
        }
    }
}

int main() {
    permutation(5, 0);
}
```

## Recursion vs Loop

Loop的優點:比較快
Recursion的優點: 很簡潔

遞迴計算第40項：0.83秒
迴圈計算第一千萬項：0.04秒

```
int main() {
    int n;
    cin >> n;
    int f[100] = {1, 1};
    for(int i=2;i<=n;++i)
        f[i] = f[i-1] + f[i-2];
    cout << f[n] << endl;
}
```

## Memorization

把計算過的項先存在陣列裡面，可以避免recursion tree長得太龐大（空間換取時間）
速度是逼近loop

```
int arr[1000000] = {1, 1};

int f(int n) {
    if(arr[n] != 0)
        return arr[n];
    arr[n] = f(n-1) + f(n-2);
    return arr[n];
}
```

## Homework
http://www.tcgs.tc.edu.tw:1218/ShowProblem?problemid=b022