Problem
A sequence x1, x2, ..., xn
is Fibonacci-like if:
n >= 3
xi + xi+1 == xi+2
for alli + 2 <= n
Given a strictly increasing array arr
of positive integers forming a sequence, return the length of the longest Fibonacci-like subsequence of arr
. If one does not exist, return 0
.
A subsequence is derived from another sequence arr
by deleting any number of elements (including none) from arr
, without changing the order of the remaining elements. For example, [3, 5, 8]
is a subsequence of [3, 4, 5, 6, 7, 8]
.
Examples
Example 1:
|
|
Example 2:
|
|
Solution
Video explanation
Here is the video explaining below methods in detail. Please check it out:
Method 1 - Using Greedy approach
To solve the problem of finding the longest Fibonacci-like subsequence, we begin by revisiting the defining property of a Fibonacci sequence:
- Every number is the sum of the two preceding numbers.
This means that if we know the first two numbers of a Fibonacci-like sequence, the rest of the sequence is uniquely determined. For example:
- Starting with 2 and 3, the sequence would proceed as 5, 8, 13, …, and so on.
This leads to the first key insight:
- If we identify the first two numbers of a subsequence, we can determine the rest by repeatedly checking for the next required number.
Code
|
|
|
|
Complexity
- Time:
O(n^2 log M)
, wheren
is the length of the array andM
is the maximum element in the array.- The two loops to select pairs
(arr[j], arr[i])
iterate over all unique pairs. This takes O(n²) time. - Inside the loop, we attempt to build a Fibonacci-like sequence starting from the chosen pair. Fibonacci numbers grow exponentially, so the number of iterations of this loop is bounded by ( \log M ), where (M) is the largest element in the array.
- The two loops to select pairs
- Space:
O(n)
Method 2 - Using DP
The problem asks us to find the longest Fibonacci-like subsequence in an array. The greedy approach works well but involves repeatedly recalculating the same information, such as whether a number exists and extending the sequence from scratch for every pair of starting numbers.
To make this process more efficient, we can use dynamic programming (DP) to:
- Reuse previously computed results: Instead of extending sequences greedily, we can keep track of the lengths of Fibonacci-like subsequences ending at specific indices in a 2D table.
- Break the problem into subproblems: For any pair of indices
(j, i)
((j < i)), we can calculate the length of the Fibonacci-like subsequence ending atarr[j]
andarr[i]
by finding the previous numberarr[k] = arr[i] - arr[j]
(if it exists and satisfies (k < j)).
So, the key idea is:
- Every Fibonacci-like subsequence of length $\geq 3$ can be determined uniquely by its last two numbers.
- Hence, we define
dp[j][i]
as the length of the longest Fibonacci-like subsequence ending at indicesj
andi
in the array.
- Hence, we define
Approach
-
Initialisation:
- Create a
dp
table of size (n \times n), where each entry is initialised to2
(indicating the minimum length for a pair). - Use a map to store the index of every number in the array for efficient lookups.
- Create a
-
Recurrence Relation:
- For each pair of indices
(j, i)
((j < i)), calculate the possible third-to-last number:arr[k] = arr[i] - arr[j]
- If
arr[k]
exists in the array and its indexk
is less thanj
, update the DP table:dp[j][i] = dp[k][j] + 1
- Otherwise, leave
dp[j][i]
as2
.
- For each pair of indices
-
Track the Maximum Length:
- For each valid pair
(j, i)
, update a variablemax_len
with the maximum value ofdp[j][i]
.
- For each valid pair
-
Iteration:
- Use two nested loops:
- Outer loop with
i
(current endpoint of the sequence). - Inner loop with
j
(second-to-last number).
- Outer loop with
- For each pair, compute the third-to-last number and update the DP table using the recurrence relation.
- Use two nested loops:
-
Final Output:
- Return
max_len
if it is greater than or equal to3
. Otherwise, return0
(indicating no valid Fibonacci-like subsequence exists).
- Return
Code
|
|
|
|
Complexity
- Time:
O(n^2)
. The two nested loops iterate over all pairs ((i, j)), contributing (O(n^2)). - Checking or retrieving
third
from the map takes (O(1)). - Space:
O(n^2)
for storing O(n^2) space DP table and O(n) space for map.