2026-03-04:最长斐波那契子数组。用go语言,给定一个只包含正整数的数组 nums。把数组中任意一段连续元素看作一个片段;如果该片段从第 3 个元素起,每一项都等于前面两项之和,则称其为斐波那契型片段。长度为 1 或 2 的片段默认满足这个条件。请找出 nums 中满足该性质的最长连续片段,并返回它的长度。
3 <= nums.length <= 100000。
1 <= nums[i] <= 1000000000。
输入: nums = [1,1,1,1,2,3,5,1]。
输出: 5。
解释:
最长的斐波那契子数组是 nums[2..6] = [1, 1, 2, 3, 5]。
[1, 1, 2, 3, 5] 是斐波那契的,因为 1 + 1 = 2, 1 + 2 = 3, 且 2 + 3 = 5。
题目来自力扣3708。
一、需求理解
你希望我基于给定的Go语言代码,详细拆解它解决“最长斐波那契子数组”问题的核心思路和执行过程,并分析该解法的时间复杂度与空间复杂度。
二、代码执行过程分步解析
我们以输入 nums = [1,1,1,1,2,3,5,1] 为例,逐步拆解代码的执行逻辑:
步骤1:初始化核心变量
- 首先获取数组长度
n = 8(数组有8个元素)。 - 初始化
ans = 2:因为题目规定长度为1或2的片段默认满足条件,所以最长长度的初始值设为2(最小有效长度)。 - 初始化
start = 0:start是当前斐波那契型片段的起始下标,用于标记当前有效片段的起点。
步骤2:遍历数组验证斐波那契规则(核心循环)
循环从 i = 2 开始(因为需要验证第3个元素是否满足“前两项之和”的规则),直到 i < n:
| i值 | nums[i] | nums[i-1]+nums[i-2] | 比较结果 | 执行逻辑 | ans值 | start值 | 说明(当前有效片段) |
|---|---|---|---|---|---|---|---|
| 2 | 1 | 1+1=2 | 不相等 | 1. ans = max(2, 2-0)=2;2. start = 2-1=1 | 2 | 1 | 原片段[0,1]无效,新起点设为1 |
| 3 | 1 | 1+1=2 | 不相等 | 1. ans = max(2, 3-1)=2;2. start = 3-1=2 | 2 | 2 | 原片段[1,2]无效,新起点设为2 |
| 4 | 2 | 1+1=2 | 相等 | 无操作 | 2 | 2 | 片段[2,3,4]有效,继续 |
| 5 | 3 | 1+2=3 | 相等 | 无操作 | 2 | 2 | 片段[2,3,4,5]有效,继续 |
| 6 | 5 | 2+3=5 | 相等 | 无操作 | 2 | 2 | 片段[2,3,4,5,6]有效,继续 |
| 7 | 1 | 3+5=8 | 不相等 | 1. ans = max(2, 7-2)=5;2. start = 7-1=6 | 5 | 6 | 原片段[2,6]有效(长度5),更新ans;新起点设为6 |
步骤3:处理最后一段未验证的有效片段
循环结束后,需要检查最后一段从 start 到数组末尾的片段是否为有效片段:
执行 return max(ans, n-start),即 max(5, 8-6)=max(5,2)=5,最终返回结果5。
步骤4:关键逻辑补充说明
- 当
nums[i] != nums[i-1]+nums[i-2]时:说明当前位置i不满足规则,因此以start为起点到i-1的片段 是当前最长的有效斐波那契片段,需要计算其长度(i-start)并更新ans;同时将start重置为i-1(因为i-1和i可能是新片段的前两个元素,符合默认有效规则)。 - 当
nums[i] == nums[i-1]+nums[i-2]时:说明当前片段仍满足规则,无需更新ans和start,继续向后验证。
三、复杂度分析
1. 时间复杂度
- 核心逻辑是一次遍历数组:循环从
i=2到i=n-1,共执行n-2次,每次循环内的操作(比较、取最大值、赋值)都是O(1)的常数时间。 - 最终的
max操作也是O(1)。 - 因此,总的时间复杂度为 O(n)(
n是数组长度),满足题目中n <= 100000的性能要求。
2. 额外空间复杂度
- 代码中仅使用了有限的几个变量(
n、ans、start、i),没有创建额外的数组、哈希表等数据结构,所有变量占用的空间与输入数组长度无关。 - 因此,总的额外空间复杂度为 O(1)(常数级空间)。
总结
- 核心思路:通过滑动窗口(双指针) 思想,用
start标记当前有效片段起点,遍历验证每个位置是否满足斐波那契规则,不满足时更新最长长度并重置起点,最终得到最长有效片段长度。 - 关键操作:循环中仅验证“当前元素是否等于前两项之和”,保证了线性时间复杂度;仅使用常数变量,空间复杂度最优。
- 复杂度结论:时间复杂度
O(n),额外空间复杂度O(1)。
Go完整代码如下:
package main
import (
"fmt"
)
func longestSubarray(nums []int) int {
n := len(nums)
ans := 2
start := 0
for i := 2; i < n; i++ {
if nums[i] != nums[i-1]+nums[i-2] {
ans = max(ans, i-start) // [start,i-1] 是斐波那契子数组
start = i - 1
}
}
return max(ans, n-start) // [start,n-1] 是斐波那契子数组
}
func main() {
nums := []int{1, 1, 1, 1, 2, 3, 5, 1}
result := longestSubarray(nums)
fmt.Println(result)
}
Python完整代码如下:
# -*-coding:utf-8-*-
def longest_subarray(nums):
n = len(nums)
ans = 2
start = 0
for i in range(2, n):
if nums[i] != nums[i-1] + nums[i-2]:
ans = max(ans, i - start) # [start,i-1] 是斐波那契子数组
start = i - 1
return max(ans, n - start) # [start,n-1] 是斐波那契子数组
def main():
nums = [1, 1, 1, 1, 2, 3, 5, 1]
result = longest_subarray(nums)
print(result)
if __name__ == "__main__":
main()
C++完整代码如下:
#include <iostream>
#include <vector>
#include <algorithm>
int longestSubarray(std::vector<int>& nums) {
int n = nums.size();
int ans = 2;
int start = 0;
for (int i = 2; i < n; i++) {
if (nums[i] != nums[i-1] + nums[i-2]) {
ans = std::max(ans, i - start); // [start,i-1] 是斐波那契子数组
start = i - 1;
}
}
return std::max(ans, n - start); // [start,n-1] 是斐波那契子数组
}
int main() {
std::vector<int> nums = {1, 1, 1, 1, 2, 3, 5, 1};
int result = longestSubarray(nums);
std::cout << result << std::endl;
return 0;
}