题解一: 递归(斐波拉契)
主要思路: 最后一块只有竖着和横着两种摆法:即 f(n) = f(n-1) + f(n-2)
递归分析:
递归边界: number = = 0 返回 0; number = 1 只能竖着放 返回 1; number = 2 可竖可横 返回 2;
递归过程: 去计算number-1和number-2
图示:
复杂度分析:
时间复杂度:,每次需要计算f(n-1),f(n-2)
空间复杂度: ,递归栈深度
实现如下:
class Solution { public: int rectCover(int number) { if(number == 0) return 0; if(number == 1) return 1; //number =1 只有一种 if(number == 2) return 2;// number = 2有两种 return rectCover(number-1) + rectCover(number-2); } };
题解二:记忆化优化递归
题解思路:从上述普通递归中,可以看到 f(n-1) 与 f(n-2) 有很多项(f(3),f(4)...)在之前已经计算过了,可以使用记忆化减少无用计算。
时间复杂度: ,遍历1~n个小矩阵,计算其中有i数量的矩阵时,摆法数量;
空间复杂度: ,利用一个标记数组f,以此来记录之前被运算过的使用i个矩阵能摆放的种类数
实现如下:
class Solution { public: int f[1001]{0}; //使用记忆数组,保存已经计算好的值。 int rectCover(int number) { if(number <= 2) return number; if(f[number]) return f[number]; //如果之前已经计算过,那么直接返回 for(int i=3;i<=number;i++) f[i] = rectCover(i-1)+rectCover(i-2); return f[number]; } };
题解三:动态规划+状态压缩
题解思路:同样是应用题解一得出的公式,只是将递归变为迭代的写法。为了最小化空间复杂度,可以使用3个变量完成这个迭代过程。
动态转移方程同题解一:f(n) = f(n-1) +f(n-2)
复杂度分析:
时间复杂度:,遍历1~n个小矩阵,计算其中有i数量的矩阵时,摆法数量;
空间复杂度:,只是用常数个临时变量存放中间值;
实现如下:
class Solution { public: int rectCover(int number) { if(number==0) return 0; int a=0,b=1,c; //使用a,b,c 表示f(n-2),f(n-1),f(n) for(int i =1;i<=number;i++) { c = a + b; a = b; b = c; } return c; } };