1. 最长连续序列算法解析
最长连续序列(Longest Consecutive Sequence)是算法面试中的经典问题,要求在一个未排序的整数数组中找到数字连续的最长序列长度。这个问题看似简单,却考察了我们对哈希表、并查集等数据结构的灵活运用能力。
实际业务中,这类算法常出现在用户行为分析(如连续登录天数统计)、金融交易监控(异常连续交易识别)等场景。我在处理电商平台的用户留存分析时,就曾用这个算法找出连续活跃用户群体。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 问题定义与暴力解法
2.1 问题精确定义
给定一个未排序的整数数组nums,我们需要返回最长连续元素序列的长度。这里的"连续"指的是数值连续,不是指数组中的位置连续。例如:
输入:[100, 4, 200, 1, 3, 2]
输出:4(因为最长连续序列是[1, 2, 3, 4])
2.2 直观的排序解法
最直观的解法是先排序后遍历:
python复制def longestConsecutive(nums):
if not nums:
return 0
nums.sort()
max_streak = 1
current_streak = 1
for i in range(1, len(nums)):
if nums[i] != nums[i-1]:
if nums[i] == nums[i-1] + 1:
current_streak += 1
else:
max_streak = max(max_streak, current_streak)
current_streak = 1
return max(max_streak, current_streak)
这种方法时间复杂度为O(nlogn),主要消耗在排序步骤。虽然能解决问题,但面试中通常期望更优的解法。
注意:处理重复数字时需要跳过,否则会影响连续序列长度的计算
3. 哈希集合法(最优解)
3.1 算法思路
利用哈希集合O(1)的查询特性,我们可以将时间复杂度优化到O(n):
- 将所有数字存入哈希集合
- 对于每个数字,检查它是否是某个连续序列的起点
- 如果是起点,则向后扩展序列直到不连续为止
- 记录过程中的最大长度
3.2 代码实现
python复制def longestConsecutive(nums):
num_set = set(nums)
max_streak = 0
for num in num_set:
# 检查是否是序列起点
if num - 1 not in num_set:
current_num = num
current_streak = 1
while current_num + 1 in num_set:
current_num += 1
current_streak += 1
max_streak = max(max_streak, current_streak)
return max_streak
3.3 复杂度分析
- 时间复杂度:O(n)。虽然看起来有嵌套循环,但每个数字最多被访问两次(一次在外部循环,一次在内部while循环)
- 空间复杂度:O(n)。需要存储哈希集合
4. 并查集解法
4.1 并查集思路
并查集(Union-Find)是处理连通性问题的利器。我们可以将连续的数字视为需要连通的元素:
- 初始化每个数字的父节点为自己
- 对于每个数字,如果num+1存在,则将两者合并
- 最后统计最大的连通分量大小
4.2 代码实现
python复制class UnionFind:
def __init__(self, nums):
self.parent = {num: num for num in nums}
self.size = {num: 1 for num in nums}
def find(self, x):
while self.parent[x] != x:
self.parent[x] = self.parent[self.parent[x]] # 路径压缩
x = self.parent[x]
return x
def union(self, x, y):
if y not in self.parent:
return
rootX = self.find(x)
rootY = self.find(y)
if rootX != rootY:
if self.size[rootX] < self.size[rootY]:
self.parent[rootX] = rootY
self.size[rootY] += self.size[rootX]
else:
self.parent[rootY] = rootX
self.size[rootX] += self.size[rootY]
def longestConsecutive(nums):
if not nums:
return 0
uf = UnionFind(nums)
for num in nums:
uf.union(num, num + 1)
return max(uf.size.values())
4.3 复杂度分析
- 时间复杂度:O(nα(n)),其中α是反阿克曼函数,可以认为是常数级
- 空间复杂度:O(n)
5. 算法比较与选择
| 方法 | 时间复杂度 | 空间复杂度 | 适用场景 |
|---|---|---|---|
| 排序法 | O(nlogn) | O(1)或O(n) | 数据量小,允许修改原数组 |
| 哈希集合法 | O(n) | O(n) | 通用场景,面试首选 |
| 并查集法 | O(nα(n)) | O(n) | 需要后续动态维护连通性 |
在实际面试中,推荐优先实现哈希集合法。它不仅效率高,而且代码简洁,能充分展示对数据结构的理解。
6. 变种问题与扩展
6.1 允许k个不连续的最长子序列
给定数组和整数k,求最多允许k处不连续时的最长连续子序列长度。例如:
输入:[1,2,3,5,6,7], k=1
输出:5(可以将5视为不连续点)
解法思路:滑动窗口维护窗口内需要"修补"的不连续点数量。
6.2 二维矩阵中的最长连续路径
在二维矩阵中寻找数值连续递增的路径的最大长度。例如:
[
[9,9,4],
[6,6,8],
[2,1,1]
]
输出:4(路径1→2→6→9)
解法思路:记忆化DFS或动态规划。
6.3 时间序列中的最长连续事件
处理带时间戳的事件流,找出连续发生的事件序列。例如用户登录记录:
[20230101, 20230102, 20230105, 20230106]
输出:2(20230101-02和20230105-06)
解法思路:先按时间排序,再应用最长连续序列算法。
7. 实际应用案例
7.1 用户行为分析
在电商平台分析用户连续活跃天数时,我们可能得到这样的数据:
[1,2,3,5,6,7,10,11,12,13]
最长连续活跃期是10-13日共4天。
实现代码:
python复制def longest_active_days(login_dates):
login_set = set(login_dates)
max_streak = 0
for date in login_set:
if date - 1 not in login_set:
current_date = date
current_streak = 1
while current_date + 1 in login_set:
current_date += 1
current_streak += 1
max_streak = max(max_streak, current_streak)
return max_streak
7.2 金融风控场景
检测异常连续交易时,可能需要找出连续的交易序列:
[1001,1002,1003,1005,1006,1008,1009,1010]
最长连续交易序列是1008-1010共3笔。
注意:实际业务中还需要结合交易金额、时间间隔等更多维度综合判断
8. 常见错误与调试技巧
8.1 边界条件处理
容易忽略的几个边界情况:
- 空数组输入
- 数组中包含重复数字
- 数组中所有数字都相同
- 超大整数导致的溢出问题
8.2 性能优化点
- 在哈希集合法中,使用num-1检查来避免重复处理非起点数字
- 并查集实现时一定要加上路径压缩和按秩合并
- 对于超大数组,考虑分块处理或并行计算
8.3 测试用例设计
建议包含以下测试用例:
python复制test_cases = [
([], 0), # 空数组
([1], 1), # 单元素
([1,1,1], 1), # 重复元素
([100,4,200,1,3,2], 4), # 标准案例
([0,3,7,2,5,8,4,6,0,1], 9), # 包含0和重复
(list(range(10**5)), 10**5) # 大数据测试
]
9. 算法可视化技巧
讲解时可以绘制这样的示意图:
初始数组:[100, 4, 200, 1, 3, 2]
哈希集合:
处理流程:
- 遇到100,检查99不存在 → 开始序列:100 → 长度1
- 遇到4,检查3存在 → 跳过
- 遇到200,检查199不存在 → 开始序列:200 → 长度1
- 遇到1,检查0不存在 → 开始序列:1,2,3,4 → 长度4
- 遇到3和2已被处理 → 跳过
最终最长序列:1-2-3-4,长度4
10. 进阶学习建议
- 推荐阅读《算法导论》中关于并查集的章节
- LeetCode相关题目:
-
- 最长连续序列(本题)
-
- 最长连续递增序列
-
- 矩阵中的最长递增路径
-
- 实际工程中的应用:
- 时间序列数据分析
- 用户行为模式识别
- 网络连通性检测
我在实际项目中发现,这类算法往往需要根据业务特点进行调整。比如在分析用户连续登录时,可能需要考虑节假日等特殊日期的影响。算法基础很重要,但灵活应用的能力同样关键。
