Syllabus - 0
內容 | 快速連結 |
---|---|
What is Recursion? 什麼是遞迴呢? | Section 1 |
Recursion Tree 用遞迴樹想像遞迴的過程 | Section 2 |
Ex O - 遞迴觀念題 | Section 3 |
Ex I - 遞迴觀念題練習 如何將數學遞迴程式遞迴? | Section 4 |
Recursion Tips 遞迴要注意的事項 | Section 5 |
Ex II - 彩帶問題 從排列組合到遞迴 | Section 6 |
Memorization - 記憶化 一個讓遞迴更快的重要技巧 | Section 7 |
Euclidean Algorithm - 輾轉相除法 | Section 8 |
Exercise III - Rhythm Doctor | Section 9 |
零和問題 嘗試用遞迴暴搜索有可能! | Section 10 |
Pruning - 剪枝一個大家都會,但很重要的技巧 | Section 11 |
Talks - 結語 | Section 12 |
重要章節
主要章節
Before Before Class - 0
Esc後大概長這樣,你可以先Esc在上下左右選你要看哪頁投影片。
What is Recursion ? - 0
What is Recursion ? - 1
What is Recursion ? - 2
Recursion
What is Recursion ? - 4
Fibonacci Sequence
*otherwise: 否則的意思
這怎麼看呢?
What is Recursion ? - 5
Fibonacci Sequence
*otherwise: 否則的意思
int f(int n){
if(n == 1 || n == 2)
return 1;
else
return f(n-1) + f(n-2);
}
What is Recursion ? - 6
有4顆相異的球
What is Recursion ? - 7
What is Recursion ? - 8
int C(int n, int m){
if(n == 0 || n == m)
return 1;
else
return C(n-1, m-1) + C(n-1, m);
}
What is Recursion Tree ? - 0
Recursion
1
2
3
4
5
6
7
8
9
What is Recursion Tree ? - 1
Recursion
What is Recursion Tree ? - 2
Tree
樹根
樹葉
樹葉
樹根
APCS 手寫練習題
接下來有三題APCS手寫題。
Exercise O - APCS遞迴手寫題1 - 0
int F (int x, int y) {
if (x<1)
return 1;
else
return F(x-y, y) + F(x-2*y, y);
}
21. 若以 F(5,2) 呼叫下方 F() 函式,執行完畢後回傳值為何?
F(5, 2) = F(3, 2) + F(1, 2)
F(3, 2) = F(1, 2) + F(-1, 2)
F(1, 2) = F(-1, 2) + F(-3, 2)
= 1 + 1 = 2
= 2 + 1 = 3
= 3 + 2 = 5
→ 答案 = 5
2 mins
Exercise O - APCS遞迴手寫題2 - 1
int f (int n) {
if (n > 3) {
return 1;
} else if (n == 2) {
return (3 + f(n+1));
} else {
return (1 + f(n+1));
}
}
24. 若以 g(4) 呼叫 g() 函式,執行完畢後回傳值為何?
int g (int n) {
int j = 0;
for (int i=1; i<=n-1; i=i+1) {
j = j + f(i);
}
return j;
}
2 mins
Exercise O - APCS遞迴手寫題2 - 2
int f (int n) {
if (n > 3) {
return 1;
} else if (n == 2) {
return (3 + f(n+1));
} else {
return (1 + f(n+1));
}
}
24. 若以 g(4) 呼叫 g() 函式,執行完畢後回傳值為何?
int g (int n) {
int j = 0;
for (int i=1; i<=n-1; i=i+1) {
j = j + f(i);
}
return j;
}
= 6
= 5
= 2
= 6 + 5 + 2
2 mins
Exercise O - APCS遞迴手寫題3 - 3
int K (int a[], int n) {
if (n >= 0)
return (K(a, n-1) + a[n]);
else
return 0;
}
int G (int n) {
int a[] = {5, 4, 3, 2, 1};
return K(a, n);
}
3. 給定右側 G(), K() 兩函式,執行 G(3) 後所回傳的值為何?
2 mins
程式練習題
接下來有一題請你用
程式實做遞迴的題目。
Exercise I - 警報器 - 0
10 mins
3s
2s
1s
1s
2s
3s
Exercise I - 警報器 - 1
10 mins
int f(int t) {
if (t == 1 || t == 3)
return 1;
else if (t <= 0)
return 0;
else
return f(t-5) + f(t-3);
}
Exercise I - 警報器 - 2
10 mins
可能數 = 長度為t-5的鳴聲種數。
可能數 = 長度為t-3的鳴聲種數。
2s
1s
2s
3s
t-5 s的組合鳴聲
t-3 s的組合鳴聲
t s的組合鳴聲
Recursion Tips - 遞迴要注意的事情 - 0
Recursion Tips - 遞迴要注意的事情 - 1
Recursion Tips - 遞迴要注意的事情 - 2
程式練習題
接下來有一題請你用程式實做遞迴的應用題。
Exercise II - 彩帶問題 - 0
15 mins
Exercise II - 彩帶問題 - 1
15 mins
?
?
?
...
n-1
?
?
?
...
n-1
?
?
?
...
Exercise II - 彩帶問題 - 2
15 mins
?
?
?
...
n-1
?
?
?
...
?
?
?
...
?
?
?
...
n-1
?
?
?
...
?
?
?
...
Exercise II - 彩帶問題 - 3
// RED = 0, ORANGE = 1, BLUE = 2
long long rec(int n, int type) {
if (n == 1)
return 1;
else if (type == RED)
return rec(n-1, BLUE);
else if (type == BLUE)
return rec(n-1, ORANGE) + rec(n-1, BLUE) + rec(n-1, RED);
else if (type == ORANGE)
return rec(n-1, BLUE) + rec(n-1, RED);
else // Should not reach here.
return 0;
}
Exercise II - 彩帶問題 - 4
// RED = 0, ORANGE = 1, BLUE = 2
long long rec(int n, int type) {
if (n == 1)
return 1;
else if (type == RED)
return rec(n-1, BLUE);
else if (type == BLUE)
return rec(n-1, ORANGE) + rec(n-1, BLUE) + rec(n-1, RED);
else if (type == ORANGE)
return rec(n-1, BLUE) + rec(n-1, RED);
else // Should not reach here.
return 0;
}
怎麼會吃TLE呢??
Memoization 記憶化 - 0
Memoization 記憶化 - 1
Memorization
bool visit[MAXN];
int DP[MAXN];
int f(int n){
if(n == 1 || n == 2)
return 1;
else if (visit[n])
return DP[n];
else {
visit[n] = true;
DP[n] = f(n-1) + f(n-2);
return DP[n];
}
}
Memorzation 記憶化 - 2
Memoization
bool visit[MAXN][MAXM];
int DP[MAXN][MAXM];
int C(int n, int m){
if(n == 0 || n == m)
return 1;
else if (visit[n][m])
return DP[n][m];
else { // visit[n][m] == false
visit[n][m] = true;
DP[n][m] = C(n-1, m-1) + C(n-1, m);
return DP[n][m];
}
}
Memoization 記憶化 - 3
Memoization
// RED = 0, ORANGE = 1, BLUE = 2
long long rec(int n, int type) {
if (n == 1)
return 1;
else if (type == RED)
return rec(n-1, BLUE);
else if (type == BLUE)
return rec(n-1, ORANGE) + rec(n-1, BLUE) + rec(n-1, RED);
else if (type == ORANGE)
return rec(n-1, BLUE) + rec(n-1, RED);
else // Should not reach here.
return 0;
}
5 mins
Memoization 記憶化 - 4
Memoization
// RED = 0, ORANGE = 1, BLUE = 2
bool visit[MAXN][MAXTYPE];
long long DP[MAXN][MAXTYPE];
long long rec(int n, int type) {
if (n == 1)
return 1;
else if (visit[n][type])
return DP[n][type];
else if (type == RED)
DP[n][type] = rec(n-1, BLUE);
else if (type == BLUE)
DP[n][type] = rec(n-1, ORANGE) + rec(n-1, BLUE) + rec(n-1, RED);
else if (type == ORANGE)
DP[n][type] = rec(n-1, BLUE) + rec(n-1, RED);
else // Should not reach here.
return 0;
visit[n][type] = true;
return DP[n][type];
}
5 mins
Euclidean Algorithm 輾轉相除法 - 0
最大公因數
Euclidean Algorithm
Euclidean Algorithm 輾轉相除法 - 1
Euclidean Algorithm
Euclidean Algorithm 輾轉相除法 - 2
Euclidean Algorithm
int GCD(int a, int b){
if(a == 0 || b == 0)
return a + b;
if (b >= a)
return GCD(a, b % a);
else
return GCD(a % b, b);
}
GCD的小小程式
Euclidean Algorithm 輾轉相除法 - 3
Euclidean Algorithm
int GCD(int a, int b){
if(a == 0 || b == 0)
return a + b;
if (b >= a)
return GCD(a, b % a);
else
return GCD(a % b, b);
}
GCD的小小程式
int GCD(int a, int b){
if(a * b == 0)
return a + b;
return GCD(b, a % b);
}
GCD的小小小小程式
Euclidean Algorithm 輾轉相除法 - 4
程式練習題
接下來有一題請你用程式實做遞迴的應用題。
Exercise III - Rhythm Doctor - 0
10 mins
10 mins
Exercise III - Rhythm Doctor - 1
A
B
3s
3s
3s
3s
4s
4s
4s
10 mins
Exercise III - Rhythm Doctor - 2
long long GCD(long a, long b){
if(a * b == 0)
return a + b;
return GCD(b, a % b);
}
long long LCM(long long a, long long b){
return a / GCD(a, b) * b;
}
10 mins
Exercise III - Rhythm Doctor - 3
int main() {
long long n, ans = 1, x;
cin >> n;
for (int i=0; i<n; i++) {
cin >> x;
ans = LCM(ans, x);
}
cout << ans << endl;
}
程式練習題
接下來有一題請你用程式實做遞迴的應用題。
Exercise IV - Subset Sum Problem 零和問題 - 0
> 20 mins
> 20 mins
(0, 0)
(1, 3)
(1, 0)
(2, 10)
(2, 7)
(2, 3)
(2, 0)
(3, 21)
(3, 14)
(3, 10)
(3, 3)
(4, 30)
(4, 19)
(4, 21)
(4, 10)
(5, 34)
(5, 25)
(5, 30)
(5, 21)
前
四
種
可
能
(看第幾個數字,
現在加到哪裡)
選
不選
+3
+7
+7
+11
+11
+9
+9
+4
+4
Exercise IV - Subset Sum Problem 零和問題 - 1
> 20 mins
Exercise IV - Subset Sum Problem 零和問題 - 2
> 20 mins
Exercise IV - Subset Sum Problem 零和問題 - 3
> 20 mins
bool rec (int i, int S) {
if (i == n)
return S == k;
else
return rec(i+1, S+A[i]) || rec(i+1, S);
}
Exercise IV - Subset Sum Problem 零和問題 - 4
> 20 mins
#include <iostream>
#define MAXN 30
using namespace std;
int k, A[MAXN], n;
bool rec (int i, int S) {
if (i == n)
return S == k;
else
return rec(i+1, S+A[i]) || rec(i+1, S);
}
int main () {
cin >> n >> k;
for (int i=0; i<n; i++)
cin >> A[i];
cout << (rec(0, 0) ? "YES" : "NO") << endl;
}
Exercise IV - Subset Sum Problem 零和問題 - 5
Pruning 剪枝 - 1
Pruning
Pruning
Pruning 剪枝 - 2
(0, 0)
(1, 3)
(1, 0)
(2, 10)
(2, 7)
(2, 3)
(2, 0)
(3, 21)
(3, 14)
(3, 10)
(3, 3)
(4, 19)
(4, 10)
(5, 25)
(5, 10)
(看第幾個數字,
現在加到哪裡)
選
不選
+3
+7
+7
+11
+11
+9
+4
(4, 23)
(4, 14)
+9
(5, 19)
(5, 14)
+4
Pruning
Pruning 剪枝 - 2
bool rec (int i, int S) {
if (S > k)
return false;
if (i == n)
return S == k;
else
return rec(i+1, S+A[i]) || rec(i+1, S);
}
題目表 - 0
Talks - 1
int fib[100] = {0, 1, 1};
for (int i=3; i<=n; i++) {
fib[i] = fib[i-1] + fib[i-2];
}
Talks - 2
Talks - 3
Talks - 0