Problem overview
The Tribonacci sequence works like Fibonacci, but each number is the sum of the three numbers before it. It starts with T(0) = 0, T(1) = 1 and T(2) = 1, and for larger n, T(n) = T(n - 1) + T(n - 2) + T(n - 3). The method tribonacci receives n and returns T(n).
The first terms are 0, 1, 1, 2, 4, 7, 13, 24, 44, 81, 149. For example, T(3) = 1 + 1 + 0 = 2, T(4) = 2 + 1 + 1 = 4 and T(5) = 4 + 2 + 1 = 7.
The statement asks for O(n) time and O(1) space.
Approach: keep only the last three values
The direct translation of the definition is a recursive function that calls itself three times. It is short, but it recomputes the same values again and again, and its running time grows exponentially. Storing every term in a list or a memo table fixes the time, but it keeps O(n) numbers in memory and a recursive version also hits Python's recursion limit of 1000 calls for large n.
The better idea is to notice what each new term needs: only the three before it. So three variables are enough. Walk up from T(2) to T(n), and at each step compute the next term and slide the window one place forward, forgetting the oldest value.
Step by step
- Handle
n < 2first.T(0)is 0 andT(1)is 1, so each answer isnitself. - Set up the window.
prev2,prevandcurrstart asT(0),T(1)andT(2), which are 0, 1 and 1. A tuple assignment does it in one line. Forn = 2the loop below does not run, andcurris already the answer. - Loop from 3 to
nwithrange(3, n + 1). The end ofrangeis exclusive, son + 1is needed to includen. - Compute
nextasprev2 + prev + curr, the next term. - Shift the window, oldest first. Assign
prevtoprev2, thencurrtoprev, thennexttocurr. Each variable is overwritten only after its old value has moved one place back. - Return
curr. After the last iteration it holdsT(n).
Tracing n = 5
| i | next | prev2 | prev | curr |
|---|---|---|---|---|
| start | 0 | 1 | 1 | |
| 3 | 2 | 1 | 1 | 2 |
| 4 | 4 | 1 | 2 | 4 |
| 5 | 7 | 2 | 4 | 7 |
The function returns 7, which matches T(5).
The solution in Python
class Solution:
def tribonacci(self, n: int) -> int:
if n < 2:
return n
prev2, prev, curr = 0, 1, 1
for i in range(3, n + 1):
next = prev2 + prev + curr
prev2 = prev
prev = curr
curr = next
return curr
Python details to notice:
- Tuple assignment.
prev2, prev, curr = 0, 1, 1evaluates the right side first and then assigns the three names. The same feature can do the whole shift in one line,prev2, prev, curr = prev, curr, next, with no ordering to get wrong. - The name
nexthides a built-in. Python has a functionnext(). Inside this method the local variable replaces it. That is harmless here, because the method never callsnext(), but a name likenxtavoids the problem. - The loop variable
iis unused. It only counts iterations._is the usual name for such a variable. - Integers have no size limit. Tribonacci numbers grow fast, roughly by a factor of 1.84 each step.
T(38)is 3831006429, which no longer fits in a signed 32-bit integer, and Python keeps going:T(100)is 98079530178586034536500564.
Complexity
Time: O(n). The loop runs n - 2 times with a constant amount of work per pass. Strictly, the numbers themselves grow with n, so additions on very large values cost more, but for the sizes in practice this is constant.
Space: O(1). Four variables are used, whatever n is.
Edge cases and common mistakes
- n = 0, 1 and 2.
T(0)returns 0 andT(1)returns 1 from the early return.T(2)skips the loop and returnscurr, which is 1. - Starting at the wrong values. This sequence starts 0, 1, 1. Other sources start with 0, 0, 1 and give a different list, so
T(3)would be 1 instead of 2. - Shifting in the wrong order. If
curr = nextcomes beforeprev = curr, the oldcurris lost andprevgets the new value. With that mistaketribonacci(5)returns 12 instead of 7. - An off-by-one range.
range(3, n)stops one term early and returnsT(n - 1). - Plain recursion. It is correct for small
n, but it recomputes values exponentially often. A memoised recursive version withfunctools.lru_cacheis fast, but it raisesRecursionErrorfor an input as large as 5000.
Testing
tribonacci(0)returns0.tribonacci(2)returns1.tribonacci(3)returns2.tribonacci(4)returns4.tribonacci(10)returns149.tribonacci(37)returns2082876103.
