本题重点不是怎么做出来,而是学习如何优化自己的算法。
问题一:
一只⻘青蛙⼀一次可以跳上1级台阶,也可以跳上2级。求该⻘青蛙跳上⼀一个n级的台阶总共有多少种跳法?
动态规划解题的三个步骤:
- 定义dp数组的含义,其中dp数组90%是二维数组,这里问题比较简单,是一维。
- 找出数组元素之间的关系式,即dp[n]是可以用dp[n-1],dp[n-2]…dp[1],来推出dp[n]的
- 找出初始值
而对于这个问题。dp[i]的含义为:跳上第I级的台阶共有dp[i]种跳法,这样dp[n]就是所要求的。
接下来是找递推关系,青蛙到达第n及台阶有两种方式,一种是从第n-1级跳上来,一种是第n-2级跳上来,所以dp[n]=dp[n-1]+dp[n-2]
寻找初始条件,dp[0]=0,dp[1]=1;这里有一个要注意的地方是当n=2时,dp[2]=2;但若按照公式计算,dp[2]=dp[1]+dp[0]=1,显然不符合,故dp[2]=2也是初始条件。
方案一:
接下来就可以写代码了
int f(int n)
{
if(n<=1)
return n;
int dp[]=new int [n+1];
dp[0]=0;
dp[1]=1;
dp[2]=2;
for(int i=3;i<=n;i++)
{
dp[i]=dp[i-1]+dp[i-2];
}
return dp[n];
}
这种做法时间复杂度是指数级别的,原因是有很多值是重复执行的,所以可以进行优化。
方案二:用Map保存已经计算过的状态
//⽤用⼀一个HashMap来保存已经计算过的状态
static Map<Integer,Integer> map = new HashMap();
public static int solve(int n){
if(n <= 2){
return n;
}else{//是否计算过
if(map.containsKey(n)){
return map.get(n);
}else{
int m = solve(n-1) + solve(n-2);
map.put(n, m);
return m;
}
}
}
方案三:我们还可以不用HashMap来保存状态
public static int solve(int n){
if(n <= 2){
return n;
}
int f1 = 0;
int f2 = 1;
int sum = 0;
for(int i = 1; i<= n; i++){
sum = f1 + f2;
f1 = f2;
f2 = sum;
}
return sum;
}