版权声明:本文为博主原创文章,欢迎大家转载,但是要注明我的文章地址。 https://blog.csdn.net/program_developer/article/details/84105231
题目链接:
题目描述:
解题思路:
2*n的大矩形,和n个2*1的小矩形
其中2*target为大矩阵的大小,target也是小矩形的个数。
有以下几种情形:
- target <= 0 大矩形为2*0,直接return 1;
- target = 1大矩形为2*1,只有一种摆放方法,return1;
- target = 2 大矩形为2*2,有两种摆放方法,return2;
- target = n 分为两步考虑:
我们假设target=8,把2*8的覆盖方法记为f(8)。用第一个1*2小矩阵去覆盖大矩阵的最左边时有两个选择,竖着放或者横着放。当竖着放的时候,右边还剩下2*7的区域,这种情形下的覆盖方法记为f(7)。接下来考虑横着放的情况。当1*2的小矩阵横着放在左上角的时候,左下角也必须横着放一个1*2的小矩形,而在右边还剩下2*6的区域,这种情形下的覆盖方法记为f(6),因此f(8)=f(7)+f(6)。此时我们可以看出,这仍然是斐波那契数列。
解题方法:
(1)递归法
已经AC的代码:
public class rectangleCover {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(RectCover(0));
}
public static int RectCover(int target) {
if(target == 0)
return 0;
else if(target == 1)
return 1;
else if(target == 2)
return 2;
else {
return RectCover(target - 1) + RectCover(target - 2);
}
}
}
(2)记忆化搜索法
由于递归的解法有很多重复的计算,我们把已经计算过的f(n)保存在数组中,等再需要f(n)的时候,直接从数组中读取,这就是记忆化搜索算法的核心思想。
已经AC的代码:
import java.util.Arrays;
public class rectangleCover {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(RectCover(33));
}
public static int[] memo;
public static int RectCover(int target) {
memo = new int[target + 1];
Arrays.fill(memo, -1);
return coverNum(target);
}
public static int coverNum(int n) {
if(memo[n] != -1)
return memo[n];
else if(n == 0)
memo[0] = 0;
else if(n == 1)
memo[1] = 1;
else if(n == 2)
memo[2] = 2;
else {
memo[n] = coverNum(n-1) + coverNum(n-2);
}
return memo[n];
}
}
(3)动态规划解法
状态转移方程:f(n)=f(n-1)+f(n-2)
边界条件:f(0) = 0、f(1) = 1、f(2) = 2。
已经AC的代码:
import java.util.Arrays;
public class rectangleCover {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(RectCover(3));
}
public static int RectCover(int target) {
int[] memo = new int[target + 1];
Arrays.fill(memo, -1);
if(target == 0)
memo[0] = 0;
if(target == 1)
memo[1] = 1;
if(target == 2)
memo[2] = 2;
if(target > 2) {
memo[0] = 0;
memo[1] = 1;
memo[2] = 2;
for(int i=3; i<=target; i++) {
if(memo[i] == -1)
memo[i] = memo[i-1] + memo[i-2];
}
}
return memo[target];
}
}
相关题目:
【1】牛客网在线编程专题《剑指offer-面试题9》斐波那契数列
【2】牛客网在线编程专题《剑指offer-面试题9:题目二扩展》变态跳台阶