剑指offer——矩形覆盖

来源:互联网 发布:明基ew2775zh 知乎 编辑:程序博客网 时间:2024/06/08 12:06

1. 问题描述

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

2. 求解方法

看似困难的题目,实际上,就是斐波那契数列的变种而已,通过画图可以清楚的看出:f(0)=0,f(1)=1,f(2)=2,f(3)=3...

那么为什么不是归纳为f(n)=n呢?

大家可以看到,如果竖放一个的话,那么每一行都会被填进去1个格子,对于每一行,相当于一步走1个格子。而如果横放着的话,那么需要放两个横放的正方形,对于每一行来讲,相当于一步走2个格子。

因此,我们只需要看其中一行,因为只要对其中一行做出操作,另外一行只有唯一的一种做法。所以这问题实际是在问,有n长的格子,可以一次走一个格子,可以一次走两个格子,问有多少种走法。

算法我们在之前的2个类似的题目中讲述太多了,因此,我们不在这赘述,给出代码:

public int RectCover(int target) {        if(target<=1){            return target;        }        else{            double root=Math.sqrt(5);            return (int)Math.round(Math.pow(((1 + root)/2), target+1) / root - Math.pow(((1 - root)/2), target+1) / root);        }    }

这是最高级的代码,当然可以使用前几级的代码。

3.算法分析

3.1 就是论事

这个没什么好说的,大家可以看一下前面两章,包括斐波那契数列以及变态跳台阶。这里对于此类斐波那契数列有了一定的介绍。

3.2 思维层面

这类题目其实可以扩充为:

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

这个其实很简单,只是往前推广了一次,其递推公式为:

f(n)=f(n1)+f(nm)

但是,如果我们把问题变为这样:

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

这个题目,我们下次再来解决。

4. 小结

这个问题本身并不难,难就难在如何想到和斐波那契数列相关,基本上采用的归纳法。然后,是对于问题本质的认识。最后,一定要学会问题转化,转化到熟悉的算法中来解决,是最快的解题过程。

0 0
原创粉丝点击