求有多少种解的问题,一般用递归能解
记忆化递归
只要能用递归解决的问题,都可以用记忆化递归
用一个数组来存储已经计算出的结果,在递归函数的一开始处,先判断当前要求的值是否已经计算出来,如果计算出来,不用递归可以直接返回了
动态规划
能用递归的问题,一般都可以用动态规划解决
青蛙跳台阶
动态规划
青蛙跳台阶问题的递归边界
n=0 return 1;这是为什么呢啊?
从动态规划的角度看,dp[2]=dp[1]+dp[0]=2,所以dp[0]=1
动态规划法:
int dp[110];
int numWays(int n)
{
memset(dp,0,sizeof(dp));//初始化,把dp和memo合并了,因为可用0区分
//base case
dp[1]=1;dp[0]=1;//dp[i]还剩i级台阶的时候有多少种跳法
int a=dp[0];
int b=dp[1];
//状态转移,状态:总台阶数量,选择:一级跳,两级跳
for(int i=2;i<=n;i++)
{
dp[i]=(dp[i-1]+dp[i-2])% 1000000007;
}
return dp[n];
}
时间复杂度: O ( n ) O(n) O(n) 因为这里只需要遍历状态n,如果是硬币问题,还需要遍历选择,时间复杂度可能就是 O ( n 2 ) O(n^2) O(n2)
空间复杂度优化
空间复杂度:
O
(
n
)
O(n)
O(n)
空间复杂度可以优化,思路和斐波那契额数列一样,因为只需要计算状态i,只需要他的前两个状态,i-1和i-2,那么就可以用是哪个变量,a,b,sum代替dp[i-2],dp[i-1]和dp[i]
int numWays(int n)
{
//base case
int a=1,b=1,sum;
if(n==1||0) sum=1;
//状态转移,状态:总台阶数量,选择:一级跳,两级跳
for(int i=2;i<=n;i++)
{
sum=(a+b)%1000000007;
a=b;
b=sum;
}
return sum;
}