【leetcode】斐波那契数与爬楼梯--动态规划

一、力扣509. 斐波那契数
题目如图:
【leetcode】斐波那契数与爬楼梯--动态规划_第1张图片

递归法就不写了,时间复杂度为O(2^N)
动态规划解法:
首先,状态转移方程直接就可以确定:
dp[i] = dp[i - 1] + dp[i - 2]

初始化条件为:
dp[0] = 0, dp[1] = 1
因为这题下标是从0开始的,又要求第N项的斐波那契数,所以容器大小为N+1。
代码如下:

int fib (int N){
	if (N <= 1) return N;
	vector<int> dp[N + 1];//注意不是dp[N]
	dp[0] = 0;
	dp[1] = 1;
	for (int i = 2; i <= N; ++i){
		dp[i] = dp[i - 1] + dp[i - 2];
	}
	return dp[N];
}

也可以想到,我们只要第N项数,并不需要整个斐波那契数列,所以我们不用把他们都存起来,因此可以进一步优化下空间复杂度:

int fib (int N){
	if(N <= 1) return N;
	int dp[2];//定义一个大小为2的数组就可以了
	dp[0] = 0;
	dp[1] = 1;
	for (int i = 2; i <= N; ++i){//i从0开始也可以,这里主要是设置循环的次数
		int sum = dp[0] + dp[1];
		dp[0] = dp[1];
		dp[1] = sum;
	}
	return dp[1];
}

这个方法最精髓的就是for循环里的三行代码,可以这样记忆:
先用sum记录前两项的和,再依次更新dp[0]和dp[1],最后循环结束返回dp[1]。

这种方法时间复杂度为O(N),而空间复杂度相对上一方法,从O(N)降为常数,即O(1)。

二、力扣70. 爬楼梯

题目如图:
【leetcode】斐波那契数与爬楼梯--动态规划_第2张图片
解这道题时我先写了一下前几项,
前五项分别为: 1 2 3 5 8
发现这不就是斐波那契数列吗,不过前两项分别为1和2,但是依然具有斐波那契数列的性质,即第N项等于前两项之和。

其实仔细一想,题目中为什么要说每次只能爬1个 或 2个台阶?这不就是说明,对于爬到第N层台阶来说,上一次到达的台阶就是第 N-1第 N-2 两种情况!
那爬到第N层台阶的方法数不就是爬到第N-1和第N-2的方法数之和吗?于是递推关系被找出来了,从逻辑上确定了这就是斐波那契数!
代码如下:

int dimbstairs (int n) {
	if (n <= 2) return n;
	int dp[3];//注意是3,不是2!
	dp[1] = 1;
	dp[2] = 2;
	for (int i = 3; i <= n; ++i){
		int sum = dp[1] + dp[2];
		dp[1] = dp[2];
		dp[2] = sum;
	}
	return dp[2];
}

这道题和上道题就一个区别,初始条件不同,题目说了,给定n是一个正整数,所以n从1开始!

但是,因为数组下标是默认以0开始的,所以写dp[1], dp[2]的时候,别忘了前面有个dp[0],因此定义数组大小时,一定是大小为3,即int dp[3],若为2则会报错!

你可能感兴趣的:(算法学习,算法,面试,力扣,数据结构)