趣学算法|斐波那契 矩阵算法

14天阅读挑战赛
努力是为了不平庸~
算法学习有些时候是枯燥的,这一次,让我们先人一步,趣学算法!

算法知识点

矩阵乘法特征:

1,当矩阵A的列数等于矩阵B的行数时,A与B可以相乘。

2,矩阵C的行数等于矩阵A的行数,C的列数等于B的列数。

3,乘积C的第m行第n列的元素等于矩阵A的第m行的元素与矩阵B的第n列对应元素乘积之和。

算法题目来源

斐波那契数列又称“斐波那契神奇数列”,是由13世纪的意大利数学家斐波那契提出的,当时是和兔子的繁殖问题有关的,它是一个很重要的数学模型。

算法题目描述

有小兔一对,若第二个月它们成年,第三个月生下小兔一对,以后每月生产一对小兔,而所生小兔亦在第二个月成年,第三个月生产另一对小兔,以后亦每月生产小兔一对,假定每产一对小兔必为一雌一雄,且均无死亡,试问一年后共有小兔几对?

算法推导

矩阵法斐波那契
F(1) = F(2) = 1
F(n) = F(n-1)+F(n-2)

矩阵转化:
[F(n) F(n-1)] 
= [F(n-1)+F(n-2) F(n-1)+0]
= [[1 1] [1 0]]   *  [F(n-1) F(n-2)]
= [[1 1] [1 0]]   *  [F(n-2)+F(n-3) F(n-3)+0]
= [[1 1] [1 0]]^2 *  [F(n-2) F(n-3)]
= [[1 1] [1 0]]^2  *  [F(n-3)+F(n-4) F(n-4)+0]
= [[1 1] [1 0]]^3 *  [F(n-3) F(n-4)]
.......
= [F(2) F(1)] * [[1 1] [1 0]]^(n-2) 

算法实现

/**
     * 矩阵法斐波那契
     * F(1) = F(2) = 1
     * F(n) = F(n-1)+F(n-2)
     * [F(n) F(n-1)]
     * = [F(n-1)+F(n-2) F(n-1)+0]
     * = [[1 1] [1 0]]   *  [F(n-1) F(n-2)]
     * = [[1 1] [1 0]]   *  [F(n-2)+F(n-3) F(n-3)+0]
     * = [[1 1] [1 0]]^2 *  [F(n-2) F(n-3)]
     * = [[1 1] [1 0]]^2  *  [F(n-3)+F(n-4) F(n-4)+0]
     * = [[1 1] [1 0]]^3 *  [F(n-3) F(n-4)]
     * .......
     * = [[1 1] [1 0]]^(n-2) * [F(2) F(1)]
     * @param n
     * @return
     */
    public static double matrixFbnq(int n){
        if(n==1){
            return 1;
        }
        if(n == 2){
            return 1;
        }
        double[][] a = new double[2][2];
        a[0][0] = 1;
        a[0][1] = 1;
        a[1][0] = 1;
        a[1][1] = 0;
        Matrix matrix = new Matrix(a);
        Matrix b = Matrixs.mutils(matrix,n-2);
        double[][] c = new double[2][1];
        c[0][0] = 1;
        c[1][0] = 1;
        Matrix e = Matrixs.mutil(b,new Matrix(c));
        return e.getMatrix()[0][0];
    }
public class Matrix{

    // 矩阵
    private double[][] matrix;
    // m x n 
    private int m;
    private int n;

    public double[][] getMatrix() {
        return matrix;
    }
    public Matrix() {
    }
    public Matrix(double[][] matrix) {
        this.matrix = matrix;
        this.m=matrix.length;
        this.n=matrix[0].length;
    }
    public Matrix(int m, int n) {
        this.matrix=new double[m][n];
        this.m=m;
        this.n=n;
    }

    public void setMatrix(double[][] matrix) {
        this.matrix = matrix;
        this.m=matrix.length;
        this.n=matrix[0].length;
    }

    public int getM() {
        return m;
    }

    public void setM(int m) {
        this.m = m;
    }

    public int getN() {
        return n;
    }

    public void setN(int n) {
        this.n = n;
    }
	
    @Override
    public String toString() {
        return "Matrix{" +
                "matrix=" + Arrays.toString(matrix) +
                '}';
    }
}
 /**
     * 矩阵的幂运算
     * @param m 矩阵对象
     * @param count  运算次数
     * @return  如果矩阵不是方阵,则矩阵无法进行
     */
    public static Matrix  mutils(Matrix m,int count)
    {
        if(m==null||m.getM()!=m.getN()){
            return null;
        }

        double[][] matrix = m.getMatrix();
        Matrix result = new Matrix(matrix);
        // [A]^count
        for (int i=0;i<count-1;i++)
        {
            result = Matrixs.mutil(result,new Matrix(matrix));
        }
        return result;
    }
    
    /**
     * 实现矩阵的乘法
     * @param p1 矩阵1
     * @param p2 矩阵2
     * @return 如果矩阵不可乘,返回null
     */
    public static Matrix mutil(Matrix p1,Matrix p2)
    {
        if (p1==null||p2==null)
        {
            return null;
        }
        if (p1.getN()!=p2.getM())
        {
            // 矩阵不可乘
            return null;
        }

        double[][] m1 = p1.getMatrix();
        double[][] m2 = p2.getMatrix();
        // 矩阵可乘
        double [][] m =new double[p1.getM()][p2.getN()];
        for (int i=0;i<p1.getM();i++)
        {
            for (int j=0;j<p2.getN();j++)
            {
                double a=0;
                // 核心
                for (int k=0;k<p1.getN();k++)
                {
                    a+=m1[i][k]*m2[k][j];
                }
                m[i][j]=a;
            }
        }
        return new Matrix(m);

    }

  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fjza1168

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值