873. 最长的斐波那契子序列的长度
这种不要求连续的,就是中间有干扰元素也可以。
根据公式,如果是菲薄,那当前元素是 X_i + X_{i+1} = X_{i+2}
同时数组长度至少为3
解法:动态规划+哈希表
外层循环整个数组,内层循环外层循环到的,这样每次就能检查X_i = X_{i+2} - X_{i+1}
当满足时,就更新此时的状态。然后更新最大长度
这个问题可以使用动态规划加哈希表来解决。具体的动态规划设计思路是使用一个二维的dp数组,其中
dp[j][k]
表示以nums[j]
和nums[k]
作为最后两个元素的斐波那契式子序列的最大长度。这里,j < k
,并且我们需要一个映射(哈希表)来快速定位数组中每个数的索引,以便能够快速检查任何两个元素之和是否也在数组中。动态规划算法步骤
- 初始化: 创建一个哈希表来存储数组中每个数的索引。这用于快速查找和确认某个数是否在数组中。
- 创建DP表: 初始化一个二维的dp数组,
dp[j][k]
表示以nums[j]
和nums[k]
作为最后两个数的斐波那契序列的最长长度。- 填充DP表: 遍历每一对
(j, k)
,对于每对(j, k)
,检查nums[k] - nums[j]
(即nums[i]
)是否存在于数组中且i < j
。如果存在,更新dp[j][k]
。- 计算结果: 最终结果为所有
dp[j][k]
中的最大值。代码实现
def lenLongestFibSubseq(self, nums: List[int]) -> int: index_map = {x: i for i, x in enumerate(nums)} # 建立数字到其索引的映射 n = len(nums) dp = defaultdict(lambda: 2) # 默认斐波那契序列长度为2(如果存在的话) max_len = 0 for k in range(n): for j in range(k): i = index_map.get(nums[k] - nums[j], None) if i is not None and i < j: # 确保找到的i位于j的前面 dp[(j, k)] = dp[(i, j)] + 1 # 更新dp[j][k] max_len = max(max_len, dp[(j, k)]) # 更新最大长度 return max_len if max_len > 2 else 0 # 如果最大长度大于2则返回,否则返回0(因为至少需要3个数形成斐波那契序列)
复杂度分析
- 时间复杂度:
O(n^2)
,其中n
是数组的长度。我们需要遍历数组中每对数字来更新dp表。- 空间复杂度:
O(n^2)
,存储dp值需要的空间。注意事项
- 初始化
dp
时,每个斐波那契序列的长度至少是2(如果存在两个数的话)。- 最终的结果需要检查最长长度是否大于2,因为任何有效的斐波那契式序列至少包含3个数字。