Python 0873.py
class Solution:
def lenLongestFibSubseq(self, arr: List[int]) -> int:
result = 0
lookup = set(arr)
seen = set() # basic cache: if (a, b) where already visited, then a longer chain exists
# start with every possible pair a, b (where a < b)
for i, a in enumerate(arr):
for b in arr[i + 1 : ]:
length = 2
# keep going while one + two exists
one = a
two = b
while one + two in lookup and ( one, two ) not in seen:
seen.add(( one, two ))
length += 1
result = max(result, length)
# prepare next step
one, two = two, one + two
return result
Difficulty
and has an acceptance rate of about 57% (300k+ submissions).
Typical patterns to solve this problem:
- Array
- Dynamic Programming
- Hash Table
AI Disclaimer
However, two years later I set up this website and used various AI tools to generate most of the walkthrough / explanations below.
See this dedicated page for more details.
Code Walkthrough
Overview
The provided implementation computes the length of the longest Fibonacci-like subsequence that can be formed from a given list of integers. It iterates over every ordered pair of distinct elements, attempts to extend a potential sequence by repeatedly checking whether the sum of the last two numbers exists in the original array, and records the maximum length found. A cache of already-processed pairs prevents redundant work, and a hash-set enables constant-time membership tests.
Key Steps
Preparing auxiliary data structures
The algorithm begins by creating a hash-set containing all values from the input array. This set is used for fast existence checks while extending a candidate sequence.
lookup = set(arr)
A second set, seen, stores ordered pairs that have already been examined. By remembering which (a, b) pairs have been processed, the algorithm avoids re-evaluating the same continuation path later in the execution.
seen = set()
Enumerating starting pairs
The outer loops select every possible ordered pair (a, b) where a precedes b in the array. The index of a is obtained from enumerate, and the slice arr[i + 1 :] yields all subsequent elements for b.
for i, a in enumerate(arr):
for b in arr[i + 1:]:
length = 2
The variable length is initialized to 2 because any pair of numbers constitutes the minimal Fibonacci-like sequence.
Extending a candidate sequence
Inside the nested loops, a while loop attempts to grow the current sequence. It checks two conditions: the sum of the last two numbers must be present in lookup, and the ordered pair (one, two) must not have been seen before. When both hold, the pair is added to seen, the length counter is incremented, and the global maximum result is updated.
one = a
two = b
while one + two in lookup and (one, two) not in seen:
seen.add((one, two))
length += 1
result = max(result, length)
one, two = two, one + two
The assignment one, two = two, one + two advances the pair to the next two numbers in the prospective Fibonacci chain.
Returning the final answer
After all pairs have been examined, the function returns the largest length discovered. If no Fibonacci-like subsequence longer than two elements exists, result remains 0.
return result
Edge Cases Handled
When the input array contains fewer than three elements, the nested loops still execute but the inner while condition never becomes true, leaving result at its initial value of 0. This correctly reflects the absence of any valid Fibonacci-like subsequence.
If the array includes duplicate values, the lookup set automatically collapses them, ensuring that membership checks are based on distinct numbers only. The algorithm’s pair enumeration respects the original ordering, so duplicate entries are still considered as separate starting points when they appear at different indices.
When a potential sequence reaches a pair that has already been recorded in seen, the while loop terminates early. This prevents infinite loops in cases where the same pair could otherwise be revisited indefinitely, such as when the array contains a repeating pattern that would otherwise cause the extension logic to cycle.
If the sum of the last two numbers is not present in lookup, the while loop stops, correctly terminating the current candidate sequence. This situation occurs frequently for random or sparse input arrays and is handled without error.
Performance Optimizations
The use of a hash-set for lookup provides constant-time checks for the existence of the next Fibonacci number, which is crucial for keeping the inner loop efficient. By storing previously processed ordered pairs in the seen set, the algorithm eliminates repeated work for the same starting pair, reducing the total number of iterations required to explore all possible sequences. The early exit from the while loop when a pair is found in seen further curtails unnecessary computation, especially in inputs where many overlapping subsequences share common prefixes. These design choices collectively ensure that the algorithm scales well with the size of the input array.
ELI5 - Simplified Explanation
Imagine there is a big collection box filled with number cards lined up in order from smallest to biggest. The goal is to find a secret sequence of numbers hiding inside that box. A secret sequence works like a family where each new number is made by adding the two numbers that came right before it. For example, if you have two and three, the next number must be five because two plus three makes five. If you have three and five, the next one must be eight because three plus five makes eight.
The computer starts by picking any two cards from the box to see if they can begin a secret chain. It keeps a little list of all the numbers in the box so it can check very quickly if the next required number is inside. After picking the first two numbers, the computer calculates what the third number should be. If that third number is hiding in the box, the chain grows longer. The computer keeps adding these numbers together to make new ones and checking if they also live in the box.
Every time it finds a new number for the chain, it records that the chain is getting longer. If it finds a long chain, it remembers how many cards are in it. It does this for every pair of cards it can possibly pick. When it is finished looking at every combination, it knows the length of the longest secret chain found during the whole hunt.
Code Quality
Complexity Analysis
As a rule of thumb, the maximum input size for one second execution time is
- factorial: up to 10 elements
- exponential: up to 20 elements
- polynomial: a few thousand elements
- loglinear: up to 100,000 elements
- linear: a few million elements
- logarithmic: a billion elements
- constant: practically unlimited
Other Solutions
Obviously, I did that after I solved the problem myself.
In general, AlgoMonster and WalkCCC solutions are high-quality and always worth a look.
I haven't checked most of the other solutions, but they might be helpful as well.
And of course, the LeetCode forum is always a good place (or even the best) to look for alternative approaches.
(click on a column header to sort the table)
| author | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| author | solutions | |||||||||
| www | AlgoMonster | C++ | Python | Java | TS | |||||
| WalkCCC | C++ | Python | Java | |||||||
| leetcode.ca | C++ | Python | JS | Java | Rust | Go | TS | |||
| LeetcodeHelp | C++ | Python | Java | |||||||
| Progiez | C++ | Python | Java | |||||||
| github | black-shadows | C++ | ||||||||
| charles-wangkai | Java | |||||||||
| everthis | JS | |||||||||
| fsq | C++ | |||||||||
| gouthampradhan | Java | |||||||||
| JoshCrozier | JS | |||||||||
| lkwq007 | Python | |||||||||
| ruoru | Rust | |||||||||
| Shamik07 | Dart | |||||||||
| suxrobGM | C# | |||||||||
| trung-hn | Python | |||||||||
| AlgoMonster | C++, Python, Java, TypeScript | |||||||||
| WalkCCC | C++, Python, Java | |||||||||
| leetcode.ca | C++, Go, Java, JavaScript, Python, Rust, TypeScript | |||||||||
| LeetcodeHelp | C++, Java, Python | |||||||||
| Progiez | C++, Java, Python | |||||||||
| black-shadows | C++, C++ | |||||||||
| charles-wangkai | Java | |||||||||
| everthis | JavaScript | |||||||||
| fsq | C++ | |||||||||
| gouthampradhan | Java | |||||||||
| JoshCrozier | JavaScript | |||||||||
| lkwq007 | Python | |||||||||
| ruoru | Rust | |||||||||
| Shamik07 | Dart | |||||||||
| suxrobGM | C# | |||||||||
| trung-hn | Python |
Videos
Similar Problems
- problem 509: Fibonacci Number
Solved On The Same Day
- problem 963: Minimum Area Rectangle II
- problem 1049: Last Stone Weight II
- problem 1186: Maximum Subarray Sum with One Deletion
- problem 1300: Sum of Mutated Array Closest to Target
Extra
- Tech Stack - my development environment and tools
- AI - how AI helped me create this website (NOT solving the problems)
- Progress - progression over time
- Quality - code quality