斐波那契数列相关简化4

看这篇文章前需要看下前面三篇文章,最起码第一第二篇是需要看一下的

斐波那契数列数列相关简化1_鱼跃鹰飞的博客-CSDN博客

斐波那契数列数列相关简化2_鱼跃鹰飞的博客-CSDN博客

斐波那契数列数列相关简化3_鱼跃鹰飞的博客-CSDN博客 

算法玩的就是套路,练练就熟悉了

再来一个:

1*2的瓷砖,把N*2的区域填满

返回铺瓷砖的方法数

这题一看也有些懵逼,我先画个图:

 哈哈,图简单吧,但是我想说什么你应该是懂的

如果第一块砖竖着铺,那后面n-1的区域使用黑盒方法选择同样的方法算数量就好了

如果第一块横着铺,那第二块只能横着铺,后面的区域就剩下n-2了,同样使用黑盒方法计算数量就好了

下面是递归的方法:

/**
     * 黑盒递归方法,返回剩余n*2块的区域能铺满的方法数
     * @param n
     * @return
     */
    public static int ways(int n) {
        if(n < 1) return 0;
        if(n == 1 || n == 2) return n;
        //第一种:n里面的第一块横着铺,第二块也没得选,只能横着铺
        int p1 = ways(n - 2);
        //第二种:n里面的第一块竖着铺,第二块开始的n-1块可以随意选择
        int p2 = ways(n -1);
        //第一块横着和第一块竖着肯定是不同的方法,加一起
        return p1 + p2;
    }

分析这个过程不难发现,这也是没有条件的严格位置依赖,符合我们第二篇文章中说的优化条件

依然是二阶矩阵,别的不多说了,上代码吧:

package dataStructure.fibonacci;

import static dataStructure.fibonacci.FibonacciStandard.matrixPower;
import static dataStructure.fibonacci.FibonacciStandard.product;

/**
 * 用1*2的瓷砖,把N*2的区域填满
 *
 * 返回铺瓷砖的方法数
 */
public class UseTileFullfill {
    /**
     * 黑盒递归方法,返回剩余n*2块的区域能铺满的方法数
     * @param n
     * @return
     */
    public static int ways(int n) {
        if(n < 1) return 0;
        if(n == 1 || n == 2) return n;
        //第一种:n里面的第一块横着铺,第二块也没得选,只能横着铺
        int p1 = ways(n - 2);
        //第二种:n里面的第一块竖着铺,第二块开始的n-1块可以随意选择
        int p2 = ways(n -1);
        //第一块横着和第一块竖着肯定是不同的方法,加一起
        return p1 + p2;
    }

    /**
     * 根据类似斐波那契数列的严格推理方式进行变化-使用矩阵的某次方
     * 时间复杂度O(logN)
     * @param n
     * @return
     */
    public static int ways2(int n) {
        if(n < 1) return 0;
        if(n == 1 || n == 2) return n;
        /*//第一种:n里面的第一块横着铺,第二块也没得选,只能横着铺
        int p1 = ways(n - 2);
        //第二种:n里面的第一块竖着铺,第二块开始的n-1块可以随意选择
        int p2 = ways(n -1);
        //第一块横着和第一块竖着肯定是不同的方法,加一起
        return p1 + p2;*/
        //根据递归方法算得前1,2,3,4项的结果分别是1,2,3,5
        //|f(3) f(2)| = |f(2) f(1)| * base
        //假设base是{{a, b}{c, d}}
        //|3 2| = |2 1| * base->2a + c = 3 2b + d =2
        //|5 3| = |3 2| * base->3a + 2c = 5 3b + 2d = 3
        //通过上面两个方程可以得到a=1, c = 1, b = 1 d = 0
        int[][] base = {{1,1},{1,0}};
        int[][] matrix21 = {{2,1}};
        int[][] matrix = matrixPower(base, n - 2);
        matrix = product(matrix21, matrix);
        return matrix[0][0];
    }

    public static void main(String[] args) {
        int n = 6;
        int ways1 = ways(n);
        System.out.println(ways1);
        int ways2 = ways2(n);
        System.out.println(ways2);
    }
}

 详细注释,方法都是用的以前的类里的,懒得写了,都是一样的,看不懂的私信我。

这个系列的题目先练到这里吧,相信对你已经没有任何挑战了,还想练的话很多递归的题目都能练这个,我再提供一个题目吧:

一个人可以一次往上迈1个台阶,也可以迈2个台阶

返回这个人迈上N级台阶的方法数

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值