阶乘公式推导
F(0) = 1
F(1) = 1 * 1 = 1 * F(0)
F(2) = 2 * 1 = 2 * F(1)
F(3) = 3 * 2 * 1 = 3 * F(2)
F(n) = n * F(n-1)
- 0的阶乘为社么是1
- 阶乘是排列组合的数量, 比如三个东西排列组合有3! (=6)种方式
- 那么如果没有东西,如何排列组合?
- ——那就“不排列组合”。“什么都不做”可以当做一种方式,i.e: 0!=1.
实现
暴力递归
int Fab(int n) {
if (n <= 1){
return 1;
}
return n * Fab(n - 1);
}
int main(){
Fab(4);
}
递归树如下
动态规划
(1)准备表。先看可变参数范围
int Fab(int n)
- 可变参数n,其取值范围: 1~N
- 所以准备一个n+1长度的数组
std::vector<int> dp(n + 1)
(2)返回值。看主函数是怎么调用它的
Fab(n)
- 应该返回dp[n];
(3)填表
(3.1)先初始化表。也就是看base case
if (n <= 1){
return 1;
}
- 所以,如下
dp[0] = 1;
dp[1] = 1;
(3.2) 再分析普通情况的依赖:
return n * Fab(n - 1);
- 其依赖前一个,所以应该从左往右填
for(int i = 2; i <= n; i++){
}
综上:
int fab(int n){
if(n <= 1){
return 1;
}
std::vector<int> dp(n + 1);
dp[0] = 1;
dp[1] = 1;
for(int i = 2; i <= n; i++){
dp[i] = i * dp[i - 1];
}
return dp[n];
}
栈模拟递归
#include <cstdio>
#include <string>
#include <vector>
#include <sys/stat.h>
#include <cstring>
#include <assert.h>
#include <stack>
using namespace std;
int Jie(int num){
if(num == 1){
return 1;
}
return num * Jie(num - 1);
}
int JieStack(int num){
assert(num > 0);
std::stack<int> stack;
stack.push(num);
int data = 0, ans = 1;
while (!stack.empty()){
data = stack.top();
stack.pop();
if(data == 1){
ans = ans * 1;
}else{
ans = ans * data;
stack.push(data - 1);
}
}
return ans;
}
int main(int argc,char **argv){
printf("%d\n", Jie(5));
printf("%d\n", JieStack(5));
return 0;
}