我们可以用21的小矩形横着或者竖着去覆盖更大的矩形。请问用n个21的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
首先对此题进行分析:
显然 f(1)=1;f(2)=2
如果有n个小矩形,那么可以分两种情况讨论:
1.第一个小矩形为竖放时,此时有f(n-1)种摆放方式
2.第一个小矩形为横放时,此时前两个小矩形都为横放,此时有f(n-2)种摆放方式
3.第一个小矩形为斜放时,题目不允许
综上,愉快的得出n>2时f(n)=f(n-1)+f(n-2),就成了斐波那契数列问题
那么就可以简单的写出如下递归:
public class Solution {
public int RectCover(int target) {
if(target<=3){ //这题里f(3)=3,就这么写了,写2也没问题
return target;
}
return RectCover(target-1)+RectCover(target-2);
}
}说到斐波那契数列,那么对斐波那契数列问题的处理做一下总结(输出第n个斐波那契数列中的数字):
1.一般的递归方法:
public class Solution {
public int Fibonacci(int n) {
if(n<=1){
return n;
}
return Fibonacci(n-1)+Fibonacci(n-2);
}
}2.初步优化:
如果是做题,那么写出来递归就行了;但实际上用递归方式计算斐波那契数列实在是太占用资源和时间了,暴力足够,但不美丽,所以我们试试用数组来处理:
public class Solution {
public int Fibonacci(int n) {
int []arr = new arr[n+1];
arr[0]=0;
arr[1]=1;
for(int i=2;i<=n;i++){
arr[i]=arr[i-1]+arr[i-2];
}
return arr[n];
}
}3.通过之前的优化,显得美丽多了,但是暴力程度又大大下降,怎么让它更暴力一点?能不能丢掉数组?
public class Solution {
public int Fibonacci(int n) {
//默认n>0
int fibo = 1;
int fibo_1 = 1;
int fibo_2 = 0;
for(int i=2;i<=n;i++){
fibo = fibo_1 + fibo_2;
fibo_2 = fibo_1;
fibo_1 = fibo;
}
return fibo;
}
}4.好了,砍掉数组舒服多了,还能不能再砍点啥?
有了,我们可以观察到,每次fibo_1经过一个循环都会等于fibo,感觉没啥用,那就砍它
public class Solution {
public int Fibonacci(int n) {
int fibo = 1;
int fibo_2 = 0;
for(int i=2;i<=n;i++){
fibo = fibo + fibo_2;
fibo_2 = fibo - fibo_2;
}
return fibo;
}
}5.究极进化!
从上面可以看到,在for循环里,一共循环了n-1次,而n又不需要作为返回值了,完全可以拿来动刀子嘛,就不用for循环里面还得整个i计数了,直接用n本身来计数
public class Solution {
public int Fibonacci(int n) {
int fibo = 1;
int fibo_2 = 0;
while(n-->1){ // 直接用n的自减(n--)来计数
fibo = fibo + fibo_2;
fibo_2 = fibo - fibo_2
}
return fibo;
}
}beautiful

京公网安备 11010502036488号