leetcode每日一题系列-第N个泰波那契数

327 阅读1分钟

这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战

leetcode-1137-第N个泰波那契数

[博客链接]

菜🐔的学习之路

掘金首页

[题目描述]

泰波那契序列 Tn 定义如下:

T0 = 0, T1 = 1, T2 = 1, 且在 n >= 0 的条件下 Tn+3 = Tn + Tn+1 + Tn+2

给你整数 n,请返回第 n 个泰波那契数 Tn 的值。

示例 1:

 输入:n = 4
输出:4
解释:
0,1,1,2,3,5
T_3 = 0 + 1 + 1 = 2
T_4 = 1 + 1 + 2 = 4
T_5 =
 示例 2: 

 输入:n = 25
输出:1389537

提示:

  • 0 <= n <= 37

  • 答案保证是一个 32 位整数,即 answer <= 23112^{31} - 1

Related Topics

  • 记忆化搜索
  • 数学
  • 动态规划
  • 👍 85 👎 0

[题目链接]

leetcode题目链接

[github地址]

代码链接

[思路介绍]

思路一:循环+非压缩数组

  • 本题和斐波那契数列很相似
  • 都是通过前几个数的状态找到最后一个数
  • 通过定义三个特殊情况判定,然后返回即可
  • 这种情况会TLE
public int tribonacci(int n) {
    if (n < 1) {
        return 0;
    }
    if (n == 1) {
        return 1;
    }
    if (n == 2){
        return 1;
    }
    if (n == 3) {
        return 2;
    }
    return tribonacci(n-1) + tribonacci(n-2) +tribonacci(n-3);
}
  • 时间复杂度O(n)
  • 空间复杂度O(n)

思路二:思路一的优化

  • 根据斐波那契数列的优化思路很容易想到
  • 当前求值只和前三个数有关
  • 所以可以直接定义三个变量
  • 循环迭代
public int tribonacci(int n) {
    if (n < 1) {
        return 0;
    }
    if (n == 1) {
        return 1;
    }
    if (n == 2) {
        return 1;
    }
    int a = 0, b = 1, c = 1;
    int res = 2;
    for (int i = 3; i <= n; i++) {
        res = a + b + c;
        a = b;
        b = c;
        c = res;
    }
    return res;
}
  • 时间复杂度O(n)
  • 空间复杂度O(1)

思路三:组合数学

  • 没错,这就是与数学有关的简单题
  • 大佬们总能找到各种各样的数学公式、数学逻辑
  • 这道题就可以使用线性代数里的矩阵来计算
  • 公式是墨鳌大佬的贡献

image.png

  • 其实吧这个矩阵的计算逻辑还是很容易求解的,问题是我想不到矩阵
  • 最后得出的矩阵的第一行即
  • [Ti0+Ti+11+Ti+20,Ti0+Ti+11+Ti+21,Ti1+Ti+11+Ti+21T_{i}*0+T_{i+1}*1+T_{i+2}*0,T_{i}*0+T_{i+1}*1+T_{i+2}*1,T_{i}*1+T_{i+1}*1+T_{i+2}*1]
  • [Ti+1,Ti+2,Ti+3T_{i+1},T_{i+2},T_{i+3}]
class Matrix {
    int[][] a = new int[3][3];

    Matrix(boolean x) {
        {
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    a[i][j] = x ? i == j ? 1 : 0 : 0;
                }
            }
        }
    }

    //乘法运算
    Matrix multi(Matrix b) {
        Matrix C = new Matrix(false);
        for (int k = 0; k < 3; k++) {
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    C.a[i][j] = (C.a[i][j] + a[i][k] * b.a[k][j]);
                }
            }
        }
        return C;
    }

    //交并运算
    Matrix babel(int n) {
        Matrix C = new Matrix(true);
        Matrix A = new Matrix(false);
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                A.a[i][j] = a[i][j];
            }
        }
        for (; n > 0; n >>= 1, A = A.multi(A)) {
            if ((n & 1) == 1) {
                C = C.multi(A);
            }
        }
        return C;
    }
}

public int tribonacci(int n) {
    Matrix A = new Matrix(false);
    A.a[0][1]=1;
    A.a[0][2]=1;
    Matrix B = new Matrix(false);
    B.a[0][2]=1;
    B.a[1][0]=B.a[1][2]=1;
    B.a[2][1]=B.a[2][2]=1;
    B=(B.babel(n));
    A=A.multi(B);
    return A.a[0][0];
}
  • 时间复杂度O(lgn)
  • 空间复杂度O(1)

思路死:玄学数学

  • 这个公式也是墨鳌大佬查到的
  • 这帮数学家是真厉害啊。

image.png

public int tribonacci(int n) {
    return (int)Math.floor((Math.pow(33.0*(99.0-17.0*Math.sqrt(33.0)),1.0/3.0)+Math.pow(33.0*(99.0+17.0*Math.sqrt(33.0)),1.0/3.0))/66.0*Math.pow((1.0+Math.pow(19.0-3.0*Math.sqrt(33.0),1.0/3.0)+Math.pow(19.0+3.0*Math.sqrt(33.0),1.0/3.0))/3.0,1.0*n)+0.5);

}
  • 时间复杂度O(1)

  • 空间复杂度O(1)

  • ToDo:今天白天要出门,先写到这里,还有dp起始也可以用,不过和之前的滚动数组差距不大,晚上回来补,顺便把周赛的补了