A sequence x1, x2, ..., xn
is Fibonacci-like if:
n >= 3
xi + xi+1 == xi+2
for all i + 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]
.
Example 1:
Input: arr = [1,2,3,4,5,6,7,8] Output: 5 Explanation: The longest subsequence that is fibonacci-like: [1,2,3,5,8].
Example 2:
Input: arr = [1,3,7,11,12,14,18] Output: 3 Explanation: The longest subsequence that is fibonacci-like: [1,11,12], [3,11,14] or [7,11,18].
Constraints:
3 <= arr.length <= 1000
1 <= arr[i] < arr[i + 1] <= 109
This problem asks us to find the length of the longest Fibonacci-like subsequence within a given strictly increasing array of positive integers. A Fibonacci-like subsequence is defined as a subsequence where each element (starting from the third) is the sum of the two preceding elements.
The most efficient approach is using dynamic programming. We'll build a table to store the lengths of Fibonacci-like subsequences.
1. Data Structures:
f[i][j]
: A 2D array (or matrix) where f[i][j]
represents the length of the longest Fibonacci-like subsequence ending with arr[i]
and arr[j]
.d
: A hash table (dictionary or map) to store the index of each element in arr
for fast lookups. This significantly optimizes the search for the third element in the Fibonacci-like subsequence.2. Initialization:
f[i][j]
to 2 for all i > j
, because any two consecutive numbers in arr
can form the beginning of a Fibonacci-like subsequence of length 2.d
with the element and its index from arr
.3. Iteration:
The core logic lies in iterating through the array. For each pair (arr[i], arr[j])
with i > j
, we check if arr[i] - arr[j]
exists in the array (arr
). If it does, let's say at index k
, and k < j
(to ensure the subsequence is strictly increasing), then we have found a potential Fibonacci-like subsequence. We update f[i][j]
to be the maximum of its current value and f[j][k] + 1
. We add 1 because we've extended the subsequence by one element (arr[i]
).
4. Result:
The maximum value in the f
array represents the length of the longest Fibonacci-like subsequence.
arr
. This is because of the nested loops iterating through all pairs of elements.f
matrix. The hash table d
takes O(n) space.Python:
class Solution:
def lenLongestFibSubseq(self, arr: List[int]) -> int:
n = len(arr)
f = [[2 if i > j else 0 for j in range(n)] for i in range(n)] # Initialize f
d = {x: i for i, x in enumerate(arr)} # Hash table for efficient lookup
ans = 0
for i in range(2, n):
for j in range(1, i):
t = arr[i] - arr[j]
if t in d and d[t] < j: # Check if t exists and k < j
f[i][j] = f[j][d[t]] + 1 # Update f[i][j]
ans = max(ans, f[i][j]) # Update the overall maximum length
return ans if ans > 2 else 0 # Return 0 if no Fibonacci-like subsequence of length >=3 found
Java:
import java.util.HashMap;
import java.util.Map;
class Solution {
public int lenLongestFibSubseq(int[] arr) {
int n = arr.length;
int[][] f = new int[n][n]; // Initialize f
Map<Integer, Integer> d = new HashMap<>(); // Hash table for efficient lookup
int ans = 0;
for (int i = 0; i < n; i++) {
d.put(arr[i], i);
for (int j = 0; j < i; j++) {
f[i][j] = 2;
}
}
for (int i = 2; i < n; i++) {
for (int j = 1; j < i; j++) {
int t = arr[i] - arr[j];
Integer k = d.get(t);
if (k != null && k < j) { // Check if t exists and k < j
f[i][j] = f[j][k] + 1; // Update f[i][j]
ans = Math.max(ans, f[i][j]); // Update the overall maximum length
}
}
}
return ans > 2 ? ans : 0; // Return 0 if no Fibonacci-like subsequence of length >=3 is found
}
}
The code in other languages (C++, Go, TypeScript, Rust, JavaScript) follows the same dynamic programming logic, just adapted to the specific syntax and data structures of that language. The key components remain the same: the f
matrix for DP, the d
hash table for efficient lookups, and the nested loops to find and extend Fibonacci-like subsequences.