LeetCode 128 最长连续序列

点此看全部题解 LeetCode必刷100题:一份来自面试官的算法地图(题解持续更新中)

生活中的算法

你小时候一定玩过数字积木吧?一堆写着不同数字的积木块散落在地上,你会不自觉地想把连续的数字找出来,按顺序排成一行。比如看到3、4、5,就会把它们放在一起,因为它们是连续的。

这就是我们今天要讲的"最长连续序列"问题的生活原型。不过,这道题更有趣的地方在于:它要求我们在不对数组排序的情况下,找出这样的连续序列。就像是在不整理积木的情况下,用眼睛找出最长的连续数字链。

问题描述

LeetCode第128题"最长连续序列"是这样描述的:给定一个未排序的整数数组nums,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。要求算法的时间复杂度为O(n)。

例如,给定nums = [100, 4, 200, 1, 3, 2],最长的连续序列是[1, 2, 3, 4],所以答案是4。

最直观的解法:排序法

最容易想到的方法就是:先把数组排序,然后找最长的连续序列。就像我们整理积木时,先把所有积木按数字大小排好,然后就能轻松找到最长的连续数字链。

具体步骤是这样的:

  1. 将数组排序
  2. 遍历排序后的数组,记录当前连续序列的长度
  3. 如果下一个数不连续,就重新开始计数
  4. 记录所有连续序列中的最大长度

让我们用一个例子来模拟这个过程:

原数组:[100, 4, 200, 1, 3, 2]
排序后:[1, 2, 3, 4, 100, 200] 遍历过程:
1 -> 当前长度=1
2 -> 连续,长度=2
3 -> 连续,长度=3
4 -> 连续,长度=4
100 -> 不连续,重新开始,长度=1
200 -> 不连续,重新开始,长度=1 最长连续序列的长度 = 4

这种思路可以用Java代码这样实现:

public int longestConsecutive(int[] nums) {
if (nums.length == 0) return 0; // 先排序
Arrays.sort(nums); int maxLength = 1;
int currentLength = 1; for (int i = 1; i < nums.length; i++) {
// 跳过重复元素
if (nums[i] == nums[i-1]) continue; // 判断是否连续
if (nums[i] == nums[i-1] + 1) {
currentLength++;
maxLength = Math.max(maxLength, currentLength);
} else {
currentLength = 1;
}
} return maxLength;
}

但这个解法的时间复杂度是O(nlogn),不满足题目要求的O(n)。我们需要想出更巧妙的方法。

优化解法:哈希集合法

仔细思考一下,每个连续序列都有一个起点(序列中的最小数字)。如果我们能快速判断一个数字是否是某个连续序列的起点,问题就简化了。

哈希集合法的原理

  1. 用哈希集合存储所有数字,实现O(1)时间的查找
  2. 对于每个数字x,如果x-1不存在,说明x可能是一个连续序列的起点
  3. 从这个起点开始,不断查找下一个数字,直到连续性破坏
  4. 记录过程中找到的最长序列

算法步骤(伪代码)

  1. 创建哈希集合,存入所有数字
  2. 遍历数组中的每个数字x:
    • 如果x-1不在集合中(说明是起点)
    • 从x开始,尝试找x+1, x+2, …直到找不到为止
    • 更新最长序列的长度
  3. 返回最长长度

示例运行

让我们用示例数组[100, 4, 200, 1, 3, 2]模拟运行过程:

首先创建哈希集合:{1, 2, 3, 4, 100, 200}

检查100:
- 99不在集合中,100是起点
- 找101,不存在
- 长度为1 检查4:
- 3在集合中,跳过 检查200:
- 199不在集合中,200是起点
- 找201,不存在
- 长度为1 检查1:
- 0不在集合中,1是起点
- 找2,存在
- 找3,存在
- 找4,存在
- 找5,不存在
- 长度为4 ...剩余数字都不是起点,跳过

Java代码实现

public int longestConsecutive(int[] nums) {
// 创建哈希集合,存入所有数字
Set<Integer> set = new HashSet<>();
for (int num : nums) {
set.add(num);
} int maxLength = 0; // 遍历set中每个数字
for (int num : set) {
// 如果num-1存在,说明num不是序列的起点,跳过
if (!set.contains(num - 1)) {
int currentNum = num;
int currentLength = 1; // 不断查找下一个数字
while (set.contains(currentNum + 1)) {
currentNum++;
currentLength++;
} maxLength = Math.max(maxLength, currentLength);
}
} return maxLength;
}

排序法vs哈希集合法

让我们比较这两种解法:

排序法的时间复杂度是O(nlogn),空间复杂度是O(1)(如果不考虑排序的空间开销)。它的优点是直观、易于理解,适合处理有序或接近有序的数据。

哈希集合法的时间复杂度是O(n),空间复杂度是O(n)。虽然需要额外的空间来存储哈希集合,但它能满足题目的时间复杂度要求。关键是它通过空间换时间的方式,避免了排序的开销。

题目模式总结

这道题体现了一个重要的算法思想:通过预处理数据结构来优化查找

这种思想在很多场景中都很有用,比如:

  • 查找数组中是否存在某个元素的补数
  • 判断数组中是否存在重复元素
  • 检查字符串中的字符是否出现过

解决这类问题的通用思路是:

  1. 观察问题中的查找模式
  2. 选择合适的数据结构来优化查找操作
  3. 在某些情况下,可以用空间换时间来提高效率

小结

通过这道题,我们不仅学会了如何找最长连续序列,更重要的是理解了"用合适的数据结构优化查找"这一重要思想。有时候,看似复杂的问题,只要换个角度思考,选择合适的数据结构,就能得到优雅的解法。

记住,算法设计不仅是about解决问题,更是about如何优雅高效地解决问题!


作者:忍者算法
公众号:忍者算法

从拼积木到最长连续序列:一道别出心裁的数组题目|LeetCode 128 最长连续序列的更多相关文章

  1. 图解leetcode —— 128. 最长连续序列

    前言: 每道题附带动态示意图,提供java.python两种语言答案,力求提供leetcode最优解. 描述: 给定一个未排序的整数数组,找出最长连续序列的长度. 要求算法的时间复杂度为 O(n). ...

  2. LeetCode 128. 最长连续序列(Longest Consecutive Sequence)

    题目描述 给定一个未排序的整数数组,找出最长连续序列的长度. 要求算法的时间复杂度为 O(n). 示例: 输入: [100, 4, 200, 1, 3, 2] 输出: 4 解释: 最长连续序列是 [1 ...

  3. Java实现 LeetCode 128 最长连续序列

    128. 最长连续序列 给定一个未排序的整数数组,找出最长连续序列的长度. 要求算法的时间复杂度为 O(n). 示例: 输入: [100, 4, 200, 1, 3, 2] 输出: 4 解释: 最长连 ...

  4. leetcode 128. 最长连续子序列

    题目描述: 给定一个未排序的整数数组,找出最长连续序列的长度. 要求算法的时间复杂度为 O(n). 示例: 输入:[100, 4, 200, 1, 3, 2] 输出:4 即最长的连续序列为 [1,2, ...

  5. leetcode 128最长连续序列

    方法一:使用快排: //排序法,时间O(nlogn),使用STL,只是验证一下思想,非正解: class Solution { public: int longestConsecutive(vecto ...

  6. 【LeetCode】128. 最长连续序列

    题目 给定一个未排序的整数数组,找出最长连续序列的长度. 要求算法的时间复杂度为O(n). 示例: 输入:[100, 4, 200, 1, 3, 2] 输出:4 解释:最长连续序列是[1, 2, 3, ...

  7. [LeetCode] 128. Longest Consecutive Sequence 求最长连续序列

    Given an unsorted array of integers, find the length of the longest consecutive elements sequence. F ...

  8. leetcode.哈希表.128最长连续序列-Java

    1. 具体题目 给定一个未排序的整数数组,找出最长连续序列的长度.要求算法的时间复杂度为 O(n). 示例: 输入: [100, 4, 200, 1, 3, 2] 输出: 4 解释: 最长连续序列是 ...

  9. 【LeetCode】最长连续序列

    [问题]给定一个未排序的整数数组,找出最长连续序列的长度. 要求算法的时间复杂度为 O(n). 示例: 输入: [, , , , , ] 输出: 解释: 最长连续序列是 [, , , ].它的长度为 ...

  10. 【编程题目】和为 n 连续正数序列

    51.和为 n 连续正数序列(数组).题目:输入一个正数 n,输出所有和为 n 连续正数序列.例如输入 15,由于 1+2+3+4+5=4+5+6=7+8=15,所以输出 3 个连续序列 1-5. 4 ...

随机推荐

  1. SpringBoot实现轻量级动态定时任务管控及组件化

    关于动态定时任务 关于在SpringBoot中使用定时任务,大部分都是直接使用SpringBoot的@Scheduled注解,如下: @Component public class TestTask ...

  2. (系列十二)Vue3+.Net8实现用户登录(超详细登录文档)

    说明 该文章是属于OverallAuth2.0系列文章,每周更新一篇该系列文章(从0到1完成系统开发). 该系统文章,我会尽量说的非常详细,做到不管新手.老手都能看懂. 说明:OverallAuth2 ...

  3. 二、FreeRTOS学习笔记-移植

    FreeRTOS移植 首先准备一个基础工程,stm32标准库或者HAL库,本实验使用HAL库版本的内存管理实验进行移植 移植步骤: 1 第一步:添加FreeRTOS源码(添加FreeRTOS源码的目的 ...

  4. [转载]Redis之缓存穿透、缓存击穿、缓存雪崩及其解决方法

    原文地址:https://mp.weixin.qq.com/s?__biz=MzU2MDY0NDQwNQ==&mid=2247483949&idx=1&sn=6c643858d ...

  5. 接口文档解决方案之Torna

    ◆一.开源项目简介 接口文档解决方案,目标是让接口文档管理变得更加方便.快捷.Torna采用团队协作的方式管理和维护接口文档,将不同形式的文档纳入进来统一维护. Torna弥补了传统文档生成工具(如s ...

  6. elasticsearch之python操作

    总结使用python对于elasticsearch的常用操作 安装 pip install elasticsearch 2. 连接 from elasticsearch import Elastics ...

  7. Codeforces Round 878 (Div3)

    B. Binary Cafe \(1 \leq n,k \leq 10^9\) 题解:思维 考虑两种情况 第一种:钱足够多,每种咖啡都可以买的情况下,答案为\(2^k\) 第二种:钱不够多,因为任一面 ...

  8. 聊一下怎么10分钟速水中危CVE

    题目是真的.今天晚上刚接触关于CVE的审计和提交.只能说:牛逼的是真牛逼,水的是真水. 我接下来教你,怎么在10分钟里找到一个CVE的中危漏洞并且提交.然后你就可以去咸鱼接单了,一个一铂快 打开htt ...

  9. MiniTomcat 系列:第一章:解锁实现基础 HTTP 服务器的奥秘

    第一步:实现基础 HTTP 服务器 在这一章中,我们将从零开始编写一个简单的 HTTP 服务器.这个服务器的基本功能是监听一个端口,接收来自客户端的 HTTP 请求,并返回一个 HTTP 响应.我们将 ...

  10. 鸿蒙UI开发快速入门 —— part11: 鸿蒙计算器开发实践

    1.前言 经过我们前面10章的学习,我们基本上可以开发出一个简单的APP了,为了巩固学习的内容,我们先开发一个计算器APP来连个手(文末有源代码),界面如下: 包含基本的计算器运算功能 支持一键清空, ...