[名企面试知识点][Java]矩形覆盖
发布于 2017-03-07 13:09 1889 次浏览 0 赞 来自 笔试面试  

题目描述

我们可以用21的小矩形横着或者竖着去覆盖更大的矩形。请问用n个21的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?

输入描述

一个大矩形

输出描述

覆盖的方法数

题目分析

设 被n个2*1的小矩形无重叠地覆盖的方法总数为 f(n)

  • 当n=1时,明显f(1)=1;

  • 当n=2时,只能两个都横着或两个都竖着放,有f(2)=2;

  • 当小矩形个数为n,来覆盖这个2*n的大矩形。第一步只有两种放法:

 ①竖着放,那么剩下的摆放总数为 f(n-1)

 

   ②横着放,那么剩下的摆放总数为 f(n-2)。因为它下面的那块也跟随着它的摆放而确定(必须是一个横着放的小矩形)。

 

很容易看出满足斐波那契数列。

斐波那契数列(Fibonacci sequence),又称黄金分割数列

在数学上,斐波纳契数列以如下被以递归的方法定义:F(0)=0,F(1)=1,F(n)=F(n-1)+F(n-2)(n≥2,n∈N*)  

指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、…… 

可以得出递推公式:

     | 1     (n=0 ) f(n) =   | 1      (n=1 )      | f(n-1)+f(n-2)  (n>=2)

解法一 (递归)  运行时间:924ms  占用内存:654k

public class Solution {
   public int RectCover(int target) {
       if(target<=1) return 1;
       return RectCover(target-1)+RectCover(target-2);
   }
}

递归效率不高,重复计算多,比如:

f(4) = f(3) + f(2);
     = f(2) + f(1) + f(1) + f(0);
     = f(1) + f(0) + f(1) + f(1) + f(0);

求f(4)就要计算三次f(1)和两次f(0),显然这是不行的。

解法二(动态规划)  运行时间:29ms 占用内存:629k

public class Solution {
   public int RectCover(int target) {
       if(target<=1) return 1;
       int i =1;//f(0)
       int j =1;//f(1)
       for(;target>=2;target--){
           j+=i;
           i=j-i;
       }
       return j;
   }
}

显然这个快很多,n>=2时,根据 f(n)=f(n-1)+f(n-2)进行依次计算,最后得出 f(target)并返回。


添加回复
回到顶部