《LeetCode之每日一题》:116.第 N 个泰波那契数

Posted 是七喜呀!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《LeetCode之每日一题》:116.第 N 个泰波那契数相关的知识,希望对你有一定的参考价值。

第 N 个泰波那契数


题目链接: 第 N 个泰波那契数

有关题目

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

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

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

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

输入:n = 25
输出:1389537
提示:

0 <= n <= 37
答案保证是一个 32 位整数,即 answer <= 2^31 - 1

题解

法一:递归(超时)

int tribonacci(int n){
    if (n == 0) return 0;
    else if (n <= 2) return 1;
    else if (n ==  3) return 2;
    else return tribonacci(n - 1) + tribonacci(n - 2) + tribonacci(n - 3);
}

法二:记忆化搜索
参考宫水三叶

int cache[38] = { 0 };
int tribonacci(int n){
    
    if (n == 0) return 0;
    else if (n <= 2) return 1;
    if (cache[n]) return cache[n];
    cache[n] = tribonacci(n - 1) + tribonacci(n - 2) + tribonacci(n - 3);
    return cache[n];
}

时间复杂度:O(N)
空间复杂度:O(N)
法三:动态规划

int tribonacci(int n){
    int dp[n + 1];
    memset(dp, 0, sizeof(dp));
    if (n == 0) return 0;
    if (n <= 2) return 1;
    dp[0] = 0, dp[1] = 1, dp[2] = 1;
    
    
    for (int i = 3; i <= n; i++){
        dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3];
    }
    return dp[n];
}

时间复杂度:O(N)
空间复杂度:O(N)

法四:滚动数组

int tribonacci(int n){
    int pre = 1, ppre = 1, pppre = 0;
    int ans = 0;
    if (n == 0) return pppre;
    if (n <= 2) return pre;
    for (int i = 3; i <= n; i++){
        ans = pre + ppre + pppre;
        pppre  = ppre;
        ppre = pre;
        pre = ans;
    }
    return ans;
}

时间复杂度:O(N)
空间复杂度:O(1)
法五:位运算

class Solution {
public:
    int tribonacci(int n) {
        int dp[4] = {0, 1, 1, 2};
        for (int i = 4; i <= n; ++i){
            dp[i & 3] = dp[(i+1) & 3] + dp[(i+2) & 3] + dp[(i+3) & 3];
        }
        return dp[n % 4];
    }
};

时间复杂度:O(N)
空间复杂度:O(1)
法六:取模运算

class Solution {
public:
    int tribonacci(int n) {
        int dp[4] = {0, 1, 1, 2};
        for (int i = 4; i <= n; ++i){
            dp[i % 4] = dp[(i+1) % 4] + dp[(i+2) % 4] + dp[(i+3) % 4];
        }
        return dp[n % 4];
    }
};

时间复杂度:O(N)
空间复杂度:O(1)

法七:矩阵快速幂

思路:
res[0][2] = res[2][0] + res[2][1] = res * [1,1,0]^T(矩阵转置->列向量)
//C++
class Solution {
public:
    int tribonacci(int n) {
        if (n == 0) {
            return 0;
        }
        if (n <= 2) {
            return 1;
        }
        //long不会溢出
        vector<vector<long>> q = {{1, 1, 1}, {1, 0, 0}, {0, 1, 0}};
        vector<vector<long>> res = pow(q, n);
        return res[2][0] + res[2][1];
    }

    vector<vector<long>> pow(vector<vector<long>>& a, long n) {
        vector<vector<long>> ret = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};
        while (n > 0) {
            if ((n & 1) == 1) {
                ret = multiply(ret, a);
            }
            n >>= 1;
            a = multiply(a, a);
        }
        return ret;
    }

    vector<vector<long>> multiply(vector<vector<long>>& a, vector<vector<long>>& b) {
        vector<vector<long>> c(3, vector<long>(3));
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                c[i][j] = a[i][0] * b[0][j] + a[i][1] * b[1][j] + a[i][2] * b[2][j];
            }
        }
        return c;
    }
};
//C
struct Matrix {
    long mat[3][3];
};

struct Matrix multiply(struct Matrix* a, struct Matrix* b) {
    struct Matrix c;
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            c.mat[i][j] = a->mat[i][0] * b->mat[0][j] + a->mat[i][1] * b->mat[1][j] + a->mat[i][2] * b->mat[2][j];
        }
    }
    return c;
};

struct Matrix qpow(struct Matrix* a, long n) {
    struct Matrix ret = {{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}};
    while (n > 0) {
        if ((n & 1) == 1) {
            ret = multiply(&ret, a);
        }
        n >>= 1;
        *a = multiply(a, a);
    }
    return ret;
}

int tribonacci(int n) {
    if (n == 0) {
        return 0;
    }
    if (n <= 2) {
        return 1;
    }
    struct Matrix q = {{{1, 1, 1}, {1, 0, 0}, {0, 1, 0}}};
    //c语言结构体传参最好传指针
    struct Matrix res = qpow(&q, n);
    return res.mat[0][2];
}

时间复杂度:O(log(N))
空间复杂度:O(1)

以上是关于《LeetCode之每日一题》:116.第 N 个泰波那契数的主要内容,如果未能解决你的问题,请参考以下文章

《LeetCode之每日一题》:208.灯泡开关

《LeetCode之每日一题》:59.第一个错误的版本

《LeetCode之每日一题》:223.第 N 位数字

《LeetCode之每日一题》:168.密钥格式化

leetcode 每日一题 60. 第k个排列

leetcode 每日一题 60. 第k个排列