學而思小猴程式設計演算法二階段課堂筆記
(一) 遞迴Ⅰ
1、 知識點概要
先給大家講個故事:從前有座山,山裡有座廟,廟裡有個小和尚講故事:
“從前有座山,山裡有座廟,廟裡有個小和尚講故事:”
““從前有座山,山裡有座廟,廟裡有個小和尚講故事:”從前有座山,山裡有座廟,廟裡有個小和尚講故事:”
……
沒錯,你沒看錯,是個故事,如果繼續這麼講下去就是一直的在遞迴一個函式:
void 講故事(){
cout << "從前有座山,山裡有座廟,廟裡有個小和尚講故事:";
void(講故事);
}
沒錯,這就是最基本的遞迴函式,但是如果你不嫌煩的話,就看下去吧
這個函式裡的故事是毫無止境的,如果我們希望會有結束,就得加判斷
什麼時候結束,(例如:進行n次,講到有人輸入停止……)
這就講到了遞迴的重要要素:終止條件
遞迴的使用情況/條件:①重複地做某件事情,每次把做事情的次數減少,做這件事情的步驟一樣
②這件事情是有終止的時候
③不會像我舉的例子一樣煩  ̄へ ̄
這就是遞迴。
2、簡單練習熱熱身(´▽`)ノ
練習一:階乘(運算子號:"!")
階乘英文為fact
求n的階乘是多少
階乘:從1*2*3*……*n
寫成程式設計“語言”:n = n*(n-1)
終止條件:1的階乘是1
int fact(int n){ if(n == 1){ return 1; } return n*fact(n-1); }
練習二:斐波那契數列
斐波那契數列英文為fibonacci,前幾項為1 1 2 3 5 8 13……,規律為第n個數為第n-1個數+第n-2個數
求斐波那契數列的第n項是多少
終止條件:第1項和第2項為1(一般題目都會告訴你,要麼你就得自己推導,但是這個是常識)
寫成程式設計“語言”:n = fibo(n-1)+fibo(n-2)
int fibo(int n){ if(n == 1 || n == 2){ return 1; } return n+fibo(n-1)+fibo(n-2); }
練習三:求最大公約數問題
求a和b的最大公約數
方法:輾轉相除法
假設我們要求60和90的最大公約數
a |
b |
a%b |
90 | 60 | 30 |
60 | 30 | 0 |
步驟如下:
1、確保a>b
2、把a%b算出來
3、如果a%b>0,把原本a的位置改為b,把b的位置改為a%b
4、再次計算a%b
5、如果a%b = 0,答案為b
int gcd(int a, int b){ if(a % b == 0){ return b; } return gcd(b,a%b); }
3、重點難題
例一 計算組合數C(n,m) - 會
C(n,m)為n個數中選出m個數,不能重複選
考慮:第n個數選不選
①選 從n個數中選m-1個數
②不選 從n-1個數中選m個數
終止條件:C(n,0) = n和m相等 = 1
int C(int n, int m){ if(m == 0 || n == m){ return 1; } return C(n,m-1)+C(n-1,m); }
例二 走格子 -
題目就不說了
可以從三個方向走,往上,往右,往右上。
m表示m列,n表示n行
到重點的位置有三個路線分別為
①從終點的下邊過來,下標為n-1,m
②從終點的左邊過來,下標為n,m-1
③從終點的左下方過來,下標為n-1,m-1
long long cnt(int n, int m){ if(m == 0 || n == 0){ return 1; } return cnt(n-1,m) + cnt(n,m-1) + cnt(n-1,m-1); }
(二) 遞迴Ⅱ
重點難題:
1、天平
輸入5個砝碼的重量,輸出把所有砝碼都放到天平兩邊的都有多少種情況。
記錄砝碼重量的陣列:w[i]
自己定義的陣列:a[i]。a[i]如果為0,表示放左邊;如果為1,表示不放;如果為2,表示放右邊
再定義兩個變數:left:表示左邊的重量;right:表示右邊的重量
void search(int p){ if(p > n){ int left = 0, right = 0; for(int i = 1;i <= n;i++){ if(a[i] == 0){ left += w[i]; } if(a[i] == 2){ right += w[i]; } if(left == right){ cnt++; } } return; } for(a[p] = 0;a[p] <= 2;a[p]++){ search(p+1); } }
2、貨幣面值
有價值w[i]的現金c[i]張。
有多少種可能湊成m元。
void search(int p){ if(p > n){//出口 int max = 0; for(int i = 1;i <= n;i++){ max += w[i]*a[i]; } if(max == m){ cnt++; } return; } for(a[p] = 0;a[p] <= c[p];a[p]++){//列舉a[p] search(p+1); } }