Tetranacci Numbers
Problem
The Tetranacci sequence generalizes Fibonacci and Tribonacci: each term after the first four is the sum of the previous four.
Recurrence (0-indexed):
T(0) = 0, T(1) = 1, T(2) = 1, T(3) = 2 T(n) = T(n-1) + T(n-2) + T(n-3) + T(n-4) for n ≥ 4.
First terms (n = 0..10): 0, 1, 1, 2, 4, 8, 15, 29, 56, 108, 208, ...
Given n, compute T(n).
Examples
Input: n = 5
Output: 4
Input: n = 9
Output: 108
Input: n = 0
Output: 0
Solution
We explore multiple methods, from exponential recursion to O(log n) matrix exponentiation.
Method 1 - Naive Recursion (Exponential)
Intuition
Directly apply the recurrence. Massive recomputation occurs (each call branches into 4 smaller calls) → exponential blowup.
Approach
Base return for n = 0..3. Otherwise sum of previous four recursive calls.
Code
C++
long long tetranacciRec(int n){
if(n==0) return 0; if(n==1||n==2) return 1; if(n==3) return 2;
return tetranacciRec(n-1)+tetranacciRec(n-2)+tetranacciRec(n-3)+tetranacciRec(n-4);
}
Go
func tetranacciRec(n int) int64 {
if n == 0 { return 0 }
if n == 1 || n == 2 { return 1 }
if n == 3 { return 2 }
return tetranacciRec(n-1) + tetranacciRec(n-2) + tetranacciRec(n-3) + tetranacciRec(n-4)
}
Java
class TetraRec {
long tetranacci(int n){
if(n==0) return 0; if(n==1||n==2) return 1; if(n==3) return 2;
return tetranacci(n-1)+tetranacci(n-2)+tetranacci(n-3)+tetranacci(n-4);
}
}
Python
def tetranacci_rec(n: int) -> int:
if n == 0:
return 0
if n in (1,2):
return 1
if n == 3:
return 2
return (tetranacci_rec(n-1) + tetranacci_rec(n-2) +
tetranacci_rec(n-3) + tetranacci_rec(n-4))
Complexity
- ⏰ Time complexity:
O(4^n)– 4-way branching, large overlap. - 🧺 Space complexity:
O(n)– recursion depth.
Method 2 - Top-Down Memoization
Intuition
Cache each n after first computation; each state depends on four smaller indices → linear number of states.
Approach
- Allocate memo array size
n+1, initialize with sentinel (e.g.-1). - Base cases for first four values.
- Recursively compute with caching.
Code
C++
#include <vector>
long long tetraMemoDfs(int n, std::vector<long long>& memo){
if(n==0) return 0; if(n==1||n==2) return 1; if(n==3) return 2;
if(memo[n]!=-1) return memo[n];
memo[n]= tetraMemoDfs(n-1,memo)+tetraMemoDfs(n-2,memo)+tetraMemoDfs(n-3,memo)+tetraMemoDfs(n-4,memo);
return memo[n];
}
long long tetranacciMemo(int n){
std::vector<long long> memo(n+1, -1);
return tetraMemoDfs(n,memo);
}
Go
func tetranacciMemo(n int) int64 {
memo := make([]int64, n+1)
for i := range memo { memo[i] = -1 }
var dfs func(int) int64
dfs = func(k int) int64 {
if k == 0 { return 0 }
if k == 1 || k == 2 { return 1 }
if k == 3 { return 2 }
if memo[k] != -1 { return memo[k] }
memo[k] = dfs(k-1)+dfs(k-2)+dfs(k-3)+dfs(k-4)
return memo[k]
}
return dfs(n)
}
Java
class TetraMemo {
long[] memo;
long dfs(int n){
if(n==0) return 0; if(n==1||n==2) return 1; if(n==3) return 2;
if(memo[n]!=-1) return memo[n];
memo[n]=dfs(n-1)+dfs(n-2)+dfs(n-3)+dfs(n-4); return memo[n];
}
long tetranacci(int n){ memo=new long[n+1]; java.util.Arrays.fill(memo,-1); return dfs(n);}
}
Python
from functools import lru_cache
@lru_cache(None)
def tetranacci_memo(n: int) -> int:
if n == 0: return 0
if n in (1,2): return 1
if n == 3: return 2
return (tetranacci_memo(n-1) + tetranacci_memo(n-2) +
tetranacci_memo(n-3) + tetranacci_memo(n-4))
Complexity
- ⏰ Time complexity:
O(n)– eachncomputed once, constant combination cost. - 🧺 Space complexity:
O(n)– memo + recursion stack.
Method 3 - Bottom-Up DP (Array)
Intuition
Iteratively build results from base up to n storing all previous terms needed.
Approach
dp[i] = dp[i-1]+dp[i-2]+dp[i-3]+dp[i-4] for i ≥ 4.
Code
C++
long long tetranacciBU(int n){
if(n==0) return 0; if(n==1||n==2) return 1; if(n==3) return 2;
std::vector<long long> dp(n+1);
dp[0]=0; dp[1]=dp[2]=1; dp[3]=2;
for(int i=4;i<=n;++i) dp[i]=dp[i-1]+dp[i-2]+dp[i-3]+dp[i-4];
return dp[n];
}
Go
func tetranacciBU(n int) int64 {
if n == 0 { return 0 }
if n == 1 || n == 2 { return 1 }
if n == 3 { return 2 }
dp := make([]int64, n+1)
dp[0]=0; dp[1],dp[2],dp[3]=1,1,2
for i:=4; i<=n; i++ { dp[i]=dp[i-1]+dp[i-2]+dp[i-3]+dp[i-4] }
return dp[n]
}
Java
class TetraBU {
long tetranacci(int n){
if(n==0) return 0; if(n==1||n==2) return 1; if(n==3) return 2;
long[] dp=new long[n+1];
dp[0]=0; dp[1]=dp[2]=1; dp[3]=2;
for(int i=4;i<=n;i++) dp[i]=dp[i-1]+dp[i-2]+dp[i-3]+dp[i-4];
return dp[n];
}
}
Python
def tetranacci_bu(n: int) -> int:
if n == 0: return 0
if n in (1,2): return 1
if n == 3: return 2
dp = [0]*(n+1)
dp[1]=dp[2]=1; dp[3]=2
for i in range(4, n+1):
dp[i] = dp[i-1]+dp[i-2]+dp[i-3]+dp[i-4]
return dp[n]
Complexity
- ⏰ Time complexity:
O(n)– one loop. - 🧺 Space complexity:
O(n)– dp array.
Method 4 - Bottom-Up Space Optimized (4 Variables)
Intuition
Only last 4 values are needed; rotate through four variables.
Approach
Maintain (a,b,c,d) representing (T(n-4), T(n-3), T(n-2), T(n-1)) and compute next.
Code
C++
long long tetranacciSpace(int n){
if(n==0) return 0; if(n==1||n==2) return 1; if(n==3) return 2;
long long a=0,b=1,c=1,d=2,cur; // corresponds to T0..T3
for(int i=4;i<=n;++i){ cur=a+b+c+d; a=b; b=c; c=d; d=cur; }
return d;
}
Go
func tetranacciSpace(n int) int64 {
if n == 0 { return 0 }
if n == 1 || n == 2 { return 1 }
if n == 3 { return 2 }
a,b,c,d := int64(0),int64(1),int64(1),int64(2)
var cur int64
for i:=4; i<=n; i++ { cur=a+b+c+d; a,b,c,d=b,c,d,cur }
return d
}
Java
class TetraSpace {
long tetranacci(int n){
if(n==0) return 0; if(n==1||n==2) return 1; if(n==3) return 2;
long a=0,b=1,c=1,d=2,cur=0;
for(int i=4;i<=n;i++){ cur=a+b+c+d; a=b; b=c; c=d; d=cur; }
return d;
}
}
Python
def tetranacci_space(n: int) -> int:
if n == 0: return 0
if n in (1,2): return 1
if n == 3: return 2
a,b,c,d = 0,1,1,2
for _ in range(4, n+1):
cur = a+b+c+d
a,b,c,d = b,c,d,cur
return d
Complexity
- ⏰ Time complexity:
O(n)– single pass. - 🧺 Space complexity:
O(1)– constant variables.
Method 5 - Matrix Exponentiation (Logarithmic)
Intuition
Any fixed-order linear recurrence can be represented via matrix multiplication. For order 4:
Let state vector V(n) = [T(n), T(n-1), T(n-2), T(n-3)]^T.
Then V(n) = M * V(n-1) where
M = | 1 1 1 1 | | 1 0 0 0 | | 0 1 0 0 | | 0 0 1 0 |
Thus V(n) = M^{n-3} * V(3) with V(3) = [2,1,1,0]^T for n ≥ 3.
Fast exponentiation computes M^{k} in O(log n) matrix multiplications (each 4x4 constant cost).
Approach
- Handle base
n < 4directly. - Binary exponentiation of 4x4 matrix.
- Multiply result by base vector to get
T(n).
Code (C++, Java, Python shown)
C++
#include <array>
using Mat4 = std::array<std::array<long long,4>,4>;
Mat4 mul(const Mat4& A, const Mat4& B){
Mat4 C{}; for(int i=0;i<4;++i) for(int j=0;j<4;++j){ long long s=0; for(int k=0;k<4;++k) s+=A[i][k]*B[k][j]; C[i][j]=s; }
return C;
}
Mat4 mpow(Mat4 base, long long exp){
Mat4 R{}; for(int i=0;i<4;++i) R[i][i]=1;
while(exp){ if(exp&1) R=mul(R,base); base=mul(base,base); exp>>=1; }
return R;
}
long long tetranacciMatrix(long long n){
if(n==0) return 0; if(n==1||n==2) return 1; if(n==3) return 2;
Mat4 M = {{{1,1,1,1},{1,0,0,0},{0,1,0,0},{0,0,1,0}}};
Mat4 P = mpow(M, n-3);
// V(3) = [2,1,1,0]^T; T(n) = first row dot V(3)
return P[0][0]*2 + P[0][1]*1 + P[0][2]*1 + P[0][3]*0;
}
Java
class TetraMatrix {
long[][] mul(long[][] A,long[][] B){
long[][] C=new long[4][4];
for(int i=0;i<4;i++) for(int j=0;j<4;j++){
long s=0; for(int k=0;k<4;k++) s+=A[i][k]*B[k][j]; C[i][j]=s; }
return C;
}
long[][] mpow(long[][] base,long exp){
long[][] R=new long[4][4]; for(int i=0;i<4;i++) R[i][i]=1;
while(exp>0){ if((exp&1)==1) R=mul(R,base); base=mul(base,base); exp >>=1; }
return R;
}
long tetranacci(long n){
if(n==0) return 0; if(n==1||n==2) return 1; if(n==3) return 2;
long[][] M={{1,1,1,1},{1,0,0,0},{0,1,0,0},{0,0,1,0}};
long[][] P= mpow(M, n-3);
return P[0][0]*2 + P[0][1]*1 + P[0][2]*1 + P[0][3]*0;
}
}
Python
from typing import List
def _mat_mul(A: List[List[int]], B: List[List[int]]) -> List[List[int]]:
return [[sum(A[i][k]*B[k][j] for k in range(4)) for j in range(4)] for i in range(4)]
def _mat_pow(M: List[List[int]], e: int) -> List[List[int]]:
R = [[int(i==j) for j in range(4)] for i in range(4)]
while e:
if e & 1:
R = _mat_mul(R, M)
M = _mat_mul(M, M)
e >>= 1
return R
def tetranacci_matrix(n: int) -> int:
if n == 0: return 0
if n in (1,2): return 1
if n == 3: return 2
M = [[1,1,1,1],[1,0,0,0],[0,1,0,0],[0,0,1,0]]
P = _mat_pow(M, n-3)
return P[0][0]*2 + P[0][1]*1 + P[0][2]*1
Complexity
- ⏰ Time complexity:
O(log n)– binary exponentiation of constant-size matrix. - 🧺 Space complexity:
O(1)– (ignoring recursion; iterative). Matrix storage constant.
Method Comparison
| Method | Time | Space | Notes |
|---|---|---|---|
| 1 Naive Recursion | O(4^n) | O(n) | Pedagogical only |
| 2 Memoization | O(n) | O(n) | Simple; top-down |
| 3 Bottom-Up Array | O(n) | O(n) | Straightforward tabulation |
| 4 Space Optimized | O(n) | O(1) | Preferred for large n (unless log method) |
| 5 Matrix Exponentiation | O(log n) | O(1) | Fast for large n; linear recurrence trick |
Notes
- For very large
n, numbers grow exponentially; consider using big integers or applying a modulus (e.g., 1e9+7) — adjust operations accordingly. - The matrix exponentiation method generalizes to any k-step Fibonacci by using a k×k companion matrix.
- If only sequential queries with increasing
narrive, maintain a rolling window (Method 4) and append new values in amortizedO(1).