news 2026/5/15 23:07:00

【Hot100-Java中等】/LeetCode 128. 最长连续序列:如何打破排序思维,实现 O(N) 复杂度?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【Hot100-Java中等】/LeetCode 128. 最长连续序列:如何打破排序思维,实现 O(N) 复杂度?

在 LeetCode 的算法题中,“最长连续序列” (Longest Consecutive Sequence)是一道非常经典的Hot 100题目。它考察的不是复杂的算法模板,而是对哈希表特性的灵活运用以及对时间复杂度的精确控制。

1. 题目核心难点

题目描述:给定一个未排序的整数数组nums,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。

关键限制请你设计并实现时间复杂度为的算法解决此问题。

为什么不能排序?

看到“连续序列”,直觉反应通常是先排序,然后遍历一遍统计。

  • 排序算法(如快速排序、归并排序)的时间复杂度下限是

  • 题目严格要求,这意味着排序是被禁止的。我们必须在不排序的情况下,通过“查找”来还原序列。


2. 核心思路:哈希表 + “跳过逻辑”

要在时间内知道“某个数字是否存在”,只能依靠哈希表 (HashSet)

步骤一:去重与快速查找

首先,将数组中所有元素放入HashSet中。

  • 目的 1:实现的查找复杂度。

  • 目的 2:去重(虽然这一步不是必须的,但遍历 Set 比遍历原数组更稳健,详见后文分析)。

步骤二:寻找序列的“起点” (关键优化)

这是算法能达到的核心原因。

假设数组是 [100, 4, 200, 1, 3, 2]。哈希表中包含了这些数字。

当我们遍历到数字 3 时,我们要不要开始数数(寻找 4, 5...)?

  • 不要。因为3的前面有2。既然2存在,3肯定不是一个连续序列的开头。我们应该等待遍历到2(甚至1)时再处理。

  • 规则只有当num - 1不在哈希表中时,num才是序列的起点,我们才开始向后计数。


3. 代码实现与详解

Java

class Solution { public int longestConsecutive(int[] nums) { // 1. 使用 HashSet 存储所有数字,实现 O(1) 查询并去重 Set<Integer> num_set = new HashSet<Integer>(); for (int num : nums) { num_set.add(num); } int longestStreak = 0; // 2. 遍历哈希表中的每个数字 for (int num : num_set) { // 3. 【关键判断】只有当 num 是序列的起点时(即 num-1 不存在),才开始匹配 if (!num_set.contains(num - 1)) { int currentNum = num; int currentStreak = 1; // 4. 不断查询 num+1, num+2... 是否存在 while (num_set.contains(currentNum + 1)) { currentNum += 1; currentStreak += 1; } // 5. 更新最大长度 longestStreak = Math.max(longestStreak, currentStreak); } } return longestStreak; } }

4. 深度解析:为什么这是 O(N)?

很多初学者看到for循环里套了一个while循环,第一反应就是:“这不是吗?”

其实不然。我们要从每个元素被访问的次数来分析:

  1. 外层循环:每个元素最多被访问 1 次。

  2. 内层while循环

    • 只有当一个数是“起点”时,才会进入while

    • 举例[1, 2, 3, 4]

      • 访问44-1存在,跳过。

      • 访问33-1存在,跳过。

      • 访问22-1存在,跳过。

      • 访问11-1不存在,是起点。进入while,依次访问2, 3, 4

    • 结论:数组中的每个数字,只会被while循环内部访问最多一次(就是在统计属于它的那个序列长度时)。

总操作次数(存入Set) +(外层遍历) +(内层while累计总次数)。

,忽略常数后为


5. 易错点分析:遍历nums还是遍历Set

在实现时,有人会习惯写成for (int num : nums)来遍历原数组。虽然在大多数情况下也能通过,但存在隐患

潜在风险:重复元素的陷阱

如果输入数组包含大量重复的“起点”,例如:

nums = [1, 1, 1, ..., 1, 2, 3, 4, ... 1000]

  • 遍历nums:程序会遇到第一个1,发现0不在,扫描一遍11000。接着遇到第二个1,又扫描一遍11000……这将导致算法退化为并超时。

  • 遍历Set(官方解法):Set天然去重。无论原数组有多少个1Set中只有一个1,内层循环只会执行一次。

因此,始终推荐遍历Set而不是原数组,这是保证算法稳定的最佳实践。

总结

解决 LeetCode 128 题的关键在于转换思维:

  1. 空间换时间:用哈希表代替排序,消除的瓶颈。

  2. 剪枝优化:通过!set.contains(x-1)这一判断,精准定位序列起点,避免了对同一个序列中间元素的重复无效计算,将复杂度严格控制在

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/12 19:25:08

Bebas Neue字体完全指南:从入门到精通的现代设计解决方案

Bebas Neue字体完全指南&#xff1a;从入门到精通的现代设计解决方案 【免费下载链接】Bebas-Neue Bebas Neue font 项目地址: https://gitcode.com/gh_mirrors/be/Bebas-Neue 在当今数字设计领域&#xff0c;一款优秀的字体往往能决定项目的视觉成败。Bebas Neue作为备…

作者头像 李华
网站建设 2026/5/10 16:39:44

SQL解析革命:告别跨数据库兼容性噩梦的终极方案

SQL解析革命&#xff1a;告别跨数据库兼容性噩梦的终极方案 【免费下载链接】JSqlParser JSQLParser/JSqlParser: 这是一个用于解析和执行SQL语句的Java库。适合用于需要解析和执行SQL语句的场景。特点&#xff1a;易于使用&#xff0c;支持多种数据库的SQL语句解析和执行&…

作者头像 李华
网站建设 2026/5/11 0:47:40

Venera漫画阅读器终极指南:一站式解决你的漫画管理烦恼

还在为手机里装了五六个漫画APP而烦恼吗&#xff1f;本地漫画格式不兼容、网络漫画资源分散、阅读体验参差不齐——这些问题在Venera漫画阅读器面前都将迎刃而解。作为一款基于Flutter开发的全平台开源应用&#xff0c;Venera重新定义了漫画阅读的标准&#xff0c;为你带来前所…

作者头像 李华
网站建设 2026/5/14 23:14:22

PyInstaller解包工具终极指南:轻松提取Python可执行文件

PyInstaller解包工具终极指南&#xff1a;轻松提取Python可执行文件 【免费下载链接】pyinstxtractor PyInstaller Extractor 项目地址: https://gitcode.com/gh_mirrors/py/pyinstxtractor PyInstaller解包工具是一款专为解包PyInstaller打包的Python可执行文件而设计的…

作者头像 李华
网站建设 2026/5/14 7:31:45

Illustrator脚本革命:从重复劳动到创意主导的设计工作流变革

在深夜的设计工作室里&#xff0c;资深设计师李明正对着屏幕叹气。他需要为30个产品图更新价格标签&#xff0c;每个标签都要手动修改文本、调整位置、检查对齐。这样的重复性工作已经耗去了他整个下午&#xff0c;而真正的创意设计还等着他来完成。这不仅仅是李明一个人的困境…

作者头像 李华
网站建设 2026/5/8 20:58:00

音频格式转换工具:处理加密音乐文件的实用方法

音频格式转换工具&#xff1a;处理加密音乐文件的实用方法 【免费下载链接】unlock-music 在浏览器中解锁加密的音乐文件。原仓库&#xff1a; 1. https://github.com/unlock-music/unlock-music &#xff1b;2. https://git.unlock-music.dev/um/web 项目地址: https://gitc…

作者头像 李华