剑指offer——矩形覆盖
问题描述
我们可以用2 * 1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2 * 1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
思路分析
当n=8,2*8的覆盖方法记为f(8);
^ ^ ^ ^ ^ ^ ^ ^ 2*8
^ ^ ^ ^ ^ ^ ^ ^
用 # 2*1 来覆盖。在最左边时有两种选择:
#
(1)竖着
# ^ ^ ^ ^ ^ ^ ^ 右边区域 剩 2*7,即求f(7).
# ^ ^ ^ ^ ^ ^ ^
(2)横着
# # ^ ^ ^ ^ ^ ^ 此时左下角只能横着放,右边区域剩 2*6,即求f(6)
^ ^ ^ ^ ^ ^ ^ ^
所以f(8)=f(7)+f(6) 即 f(n)=f(n-1)+f(n-2); f(n)其实仍为斐波那契数列
所以
f
(
n
)
=
{
1
n
=
1
2
n
=
2
f
(
n
−
1
)
+
f
(
n
−
2
)
n
>
2
f(n) = \begin{cases} 1 & n=1 \\ 2 & n= 2 \\ f(n-1)+f(n-2) & n>2 \end{cases}
f(n)=⎩⎪⎨⎪⎧12f(n−1)+f(n−2)n=1n=2n>2
解法一 :直接用公式,但是效率低。
public class Solution {
public int RectCover(int target) {
if(target<=0){
return 0;
}
if(target==1||target==2){
return target;
}
return RectCover(target-1)+RectCover(target-2);
}
}
解法二:把已经得到的数列的中间项保存下来。下次计算的时候先查找。
代码
public class Solution {
public int RectCover(int target) {
int result[]={0,1,2};
if(target<3){
return result[target];
}
int RectCover_NMinusOne=2;
int RectCover_NMinusTwo=1;
int RectCover_N=0;
for(int i=3;i<=target;i++){
RectCover_N=RectCover_NMinusOne+RectCover_NMinusTwo;
RectCover_NMinusTwo=RectCover_NMinusOne;
RectCover_NMinusOne=RectCover_N;
}
return RectCover_N;
}
}