题目描述
我们可以用21的小矩形横着或者竖着去覆盖更大的矩形。请问用n个21的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
比如n=3时,2*3的矩形块有3种覆盖方法:
思路
如何覆盖取决于,每一次的选择
- 如果是 竖 | 着放着,相当于后面的 n-1个竖行可以构成一个新的矩形
- 如果是 横 — 着放着,相当于后面的 n-2个竖行可以构成一个新的矩形
- 例如,n=3的时候,
f(3) = f(n-1) + f(n-2) = f(2) + f(1)
- 例如,n=2的时候,
f(2) = f(n-1) + f(n-2) = f(1) + f(0)
f(0)表示两块竖的矩形区域,偏偏放了一个横的,所以这样只有一个放法了
f(1)表示两块竖的矩形区域,放了一个竖的,另一个竖的也只有一个方法了
这里需要特别注意一个特例,如果target初始为0的话,说明矩形一开始是空的,所以返回 0
代码:
- 递归
public class Solution {
public int RectCover(int target) {
if(target == 0) return 0;
return helper(target);
}
public int helper(int target){
if(target == 0) return 1;
if(target == 1) return 1;
return helper(target-1)+helper(target-2);
}
}
- 记忆化递归
public class Solution {
Integer[] memory;
public int RectCover(int target) {
if(target == 0) return 0;
memory = new Integer[target+1];
memory[0] = 1;
memory[1] = 1;
return helper(target);
}
public int helper(int target){
if(memory[target] == null){
memory[target] = helper(target-1) + helper(target-2);
}
return memory[target];
}
}
- 迭代
public class Solution {
Integer[] memory;
public int RectCover(int target) {
if(target == 0) return 0;
int a = 1, b=1;
// 第一次迭代的时候, f(0) + f(1) = f(2)|| b=f(2),a=f(1)
for(int i=0; i<target; i++){
int temp = b;
b = a+b;
a = temp;
}
return a;
}
}