参考答案
【新手入门】LeetCode 128. 最长连续序列:Java & JavaScript双语言详解
目录
- 题目描述
- 核心概念解析
- 2.1 什么是连续序列?
- 2.2 解题关键思路
- Java实现
- 3.1 哈希集合法(最优解)
- 3.2 排序法(次优解)
- JavaScript实现
- 4.1 哈希集合法
- 4.2 排序法
- 复杂度分析
- 边界条件与注意事项
- 总结与拓展
1. 题目描述
给定一个未排序的整数数组 nums
,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。
示例:
输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4],长度为4。
要求:
- 时间复杂度为 O(n) 的算法。
2. 核心概念解析
2.1 什么是连续序列?
- 定义:一组连续递增的整数(如
[5,6,7]
),但它们在原数组中可能是分散的。 - 关键点:序列中的数字在原数组中不需要连续存储。
2.2 解题关键思路
- 方法一:哈希集合法(最优)
- 使用哈希集合存储所有数字,快速判断某个数是否存在。
- 遍历数组,对每个数检查它是否是连续序列的起点(即
num-1
不在集合中),然后向后扩展序列。
- 方法二:排序法(次优)
- 先排序数组,然后遍历统计连续序列的长度(不满足O(n)要求,但易于理解)。
3. Java实现
3.1 哈希集合法(时间复杂度O(n))
import java.util.HashSet;
import java.util.Set;
class Solution {
public int longestConsecutive(int[] nums) {
Set<Integer> numSet = new HashSet<>();
for (int num : nums) {
numSet.add(num);
}
int maxLength = 0;
for (int num : numSet) {
// 检查是否是序列起点(即num-1不在集合中)
if (!numSet.contains(num - 1)) {
int currentNum = num;
int currentLength = 1;
// 向后扩展序列
while (numSet.contains(currentNum + 1)) {
currentNum++;
currentLength++;
}
maxLength = Math.max(maxLength, currentLength);
}
}
return maxLength;
}
}
3.2 排序法(时间复杂度O(nlogn))
import java.util.Arrays;
class Solution {
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] + 1) {
currentLength++;
maxLength = Math.max(maxLength, currentLength);
} else if (nums[i] != nums[i - 1]) {
currentLength = 1; // 重置计数
}
}
return maxLength;
}
}
4. JavaScript实现
4.1 哈希集合法
function longestConsecutive(nums) {
const numSet = new Set(nums);
let maxLength = 0;
for (const num of numSet) {
// 检查是否是序列起点
if (!numSet.has(num - 1)) {
let currentNum = num;
let currentLength = 1;
// 向后扩展序列
while (numSet.has(currentNum + 1)) {
currentNum++;
currentLength++;
}
maxLength = Math.max(maxLength, currentLength);
}
}
return maxLength;
}
4.2 排序法
function longestConsecutive(nums) {
if (nums.length === 0) return 0;
nums.sort((a, b) => a - b);
let maxLength = 1;
let currentLength = 1;
for (let i = 1; i < nums.length; i++) {
if (nums[i] === nums[i - 1] + 1) {
currentLength++;
maxLength = Math.max(maxLength, currentLength);
} else if (nums[i] !== nums[i - 1]) {
currentLength = 1; // 重置计数
}
}
return maxLength;
}
5. 复杂度分析
方法 | 时间复杂度 | 空间复杂度 | 适用场景 |
---|---|---|---|
哈希集合法 | O(n) | O(n) | 满足题目O(n)要求 |
排序法 | O(nlogn) | O(1)或O(n) | 不推荐用于本题 |
6. 边界条件与注意事项
- 空数组:直接返回
0
。 - 重复数字:哈希集合法自动去重,排序法需跳过重复项(如
[1,2,0,1]
)。 - 负数处理:哈希法无需特殊处理,排序法需正确比较大小。
7. 总结与拓展
- 哈希集合法:最优解,核心是找到序列起点并向后扩展。
- 排序法:虽然简单,但不满足题目对时间复杂度的要求。
- 变种题目:
- 674. 最长连续递增序列(要求原数组连续)
- 300. 最长递增子序列(非连续)
📌 下期预告:《LeetCode 674:如何高效处理连续递增序列?》
🔗 相关推荐:LeetCode 哈希表专题
如果有帮助,请点赞收藏支持! 🚀
博客标题:【算法入门】力扣题128:最长连续序列的Java与JavaScript解法
目录
- 引言
- 问题描述
- 算法分析
- Java解法
- 4.1 暴力解法
- 4.2 排序+双指针解法
- 4.3 哈希表+排序解法
- JavaScript解法
- 5.1 暴力解法
- 5.2 排序+双指针解法
- 5.3 哈希表+排序解法
- 总结
- 参考文献
1. 引言
在算法学习的过程中,力扣(LeetCode)是一个非常好的平台,它提供了大量的编程题目供我们练习。今天,我们将一起探讨力扣题128:最长连续序列的解法。这个问题考察了我们对数组、排序、双指针、哈希表等算法知识点的理解和应用。
2. 问题描述
给定一个未排序的整数数组 nums
,找出其中最长连续序列的长度。要求算法的时间复杂度为O(n)。
3. 算法分析
解决这个问题,我们可以考虑以下几种方法:
- 暴力解法:对于数组中的每个元素,检查以该元素为起点的连续序列长度。这种方法的时间复杂度为O(n^2),不满足题目要求。
- 排序+双指针:首先对数组进行排序,然后使用双指针遍历数组,跳过重复的元素,计算连续序列的长度。这种方法的时间复杂度为O(nlogn),也不满足题目要求。
- 哈希表+排序:使用哈希表存储数组中的元素,然后对哈希表的键进行排序,最后遍历排序后的键,计算连续序列的长度。这种方法的时间复杂度为O(n),满足题目要求。
4. Java解法
4.1 暴力解法
public int longestConsecutive(int[] nums) {
if (nums.length == 0) return 0;
int longestStreak = 0;
Set<Integer> numSet = new HashSet<>();
for (int num : nums) {
numSet.add(num);
}
for (int num : numSet) {
if (num - 1 != numSet) {
int currentNum = num;
int currentStreak = 1;
while (numSet.contains(currentNum + 1)) {
currentNum += 1;
currentStreak += 1;
}
longestStreak = Math.max(longestStreak, currentStreak);
}
}
return longestStreak;
}
4.2 排序+双指针解法
public int longestConsecutive(int[] nums) {
if (nums.length == 0) return 0;
Arrays.sort(nums);
int longestStreak = 1;
int currentStreak = 1;
for (int i = 1; i < nums.length; i++) {
if (nums[i] != nums[i - 1]) {
if (nums[i] == nums[i - 1] + 1) {
currentStreak++;
} else {
longestStreak = Math.max(longestStreak, currentStreak);
currentStreak = 1;
}
}
}
return Math.max(longestStreak, currentStreak);
}
4.3 哈希表+排序解法
public int longestConsecutive(int[] nums) {
if (nums.length == 0) return 0;
Set<Integer> numSet = new HashSet<>();
for (int num : nums) {
numSet.add(num);
}
int longestStreak = 0;
for (int num : numSet) {
if (num - 1 != numSet) {
int currentNum = num;
int currentStreak = 1;
while (numSet.contains(currentNum + 1)) {
currentNum += 1;
currentStreak += 1;
}
longestStreak = Math.max(longestStreak, currentStreak);
}
}
return longestStreak;
}
5. JavaScript解法
5.1 暴力解法
function longestConsecutive(nums) {
if (nums.length === 0) return 0;
let longestStreak = 0;
const numSet = new Set(nums);
for (let num of numSet) {
if (!numSet.has(num - 1
博客标题:从零开始:Java与JavaScript实现最长连续序列问题
目录
1. 引言
最长连续序列问题是一个经典的编程问题,要求找出给定数组中最长的连续序列的长度。本文将分别使用Java和JavaScript两种编程语言来解答这个问题,并详细解释其实现思路和代码。
2. 问题分析
给定一个未排序的整数数组,找出最长连续序列的长度。例如,对于数组 [100, 4, 200, 1, 3, 2]
,最长连续序列是 [1, 2, 3, 4]
,其长度为4。
3. Java实现
3.1 算法思路
- 使用HashSet存储数组中的所有元素,以便快速检查元素是否存在。
- 遍历数组,对于每个元素,检查它是否是某个连续序列的开始。
- 如果是,则递增地检查后续元素,直到序列结束。
- 更新最长连续序列的长度。
3.2 代码实现
import java.util.HashSet;
import java.util.Set;
public class LongestConsecutiveSequence {
public int longestConsecutive(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
Set<Integer> numSet = new HashSet<>();
for (int num : nums) {
numSet.add(num);
}
int longestSeq = 0;
for (int num : nums) {
// 检查是否是序列的开始
if (!numSet.contains(num - 1)) {
int currentNum = num;
int currentSeq = 1;
// 检查连续序列
while (numSet.contains(currentNum + 1)) {
currentNum++;
currentSeq++;
}
// 更新最长序列
longestSeq = Math.max(longestSeq, currentSeq);
}
}
return longestSeq;
}
}
4. JavaScript实现
4.1 算法思路
与Java实现类似,JavaScript中也可以使用Set来存储数组元素,并遍历数组来查找最长连续序列。
4.2 代码实现
function longestConsecutive(nums) {
if (!nums || nums.length === 0) {
return 0;
}
const numSet = new Set(nums);
let longestSeq = 0;
for (let num of nums) {
// 检查是否是序列的开始
if (!numSet.has(num - 1)) {
let currentNum = num;
let currentSeq = 1;
// 检查连续序列
while (numSet.has(currentNum + 1)) {
currentNum++;
currentSeq++;
}
// 更新最长序列
longestSeq = Math.max(longestSeq, currentSeq);
}
}
return longestSeq;
}
5. 总结
通过本文,我们学习了如何使用Java和JavaScript解决最长连续序列问题。这两种语言都提供了简单而有效的方法来处理这类问题,通过使用Set来优化查找效率。希望这篇文章能帮助你更好地理解并掌握这一知识点。
好的,我很乐意为你提供详细的解答和博客内容。以下是一篇新手入门博客,包含Java和JavaScript的解答以及相关知识点的详细介绍。
博客标题: 从零开始学习力扣题 128. 最长连续序列
目录:
-
问题描述
-
Java解答
2.1 暴力解法
2.2 哈希表解法 -
JavaScript解答
3.1 暴力解法
3.2 哈希表解法 -
知识点总结
4.1 连续序列
4.2 哈希表
4.3 时间复杂度和空间复杂度 -
问题描述
力扣题 128. 最长连续序列要求给定一个未排序的整数数组 nums,找出其中最长连续元素序列的长度。
连续序列是指数组中相邻元素差为1的序列。例如,输入 [100, 4, 200, 1, 3, 2],输出 4,因为最长的连续序列是 [1, 2, 3, 4]。
- Java解答
2.1 暴力解法
public int longestConsecutive(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
int maxLength = 0;
for (int num : nums) {
int currentNum = num;
int currentLength = 1;
while (isContain(nums, currentNum + 1)) {
currentNum += 1;
currentLength += 1;
}
maxLength = Math.max(maxLength, currentLength);
}
return maxLength;
}
private boolean isContain(int[] nums, int target) {
for (int num : nums) {
if (num == target) {
return true;
}
}
return false;
}
2.2 哈希表解法
public int longestConsecutive(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
Set<Integer> numSet = new HashSet<>();
for (int num : nums) {
numSet.add(num);
}
int maxLength = 0;
for (int num : nums) {
if (!numSet.contains(num - 1)) {
int currentNum = num;
int currentLength = 1;
while (numSet.contains(currentNum + 1)) {
currentNum += 1;
currentLength += 1;
}
maxLength = Math.max(maxLength, currentLength);
}
}
return maxLength;
}
- JavaScript解答
3.1 暴力解法
var longestConsecutive = function(nums) {
if (!nums || nums.length === 0) {
return 0;
}
let maxLength = 0;
for (let num of nums) {
let currentNum = num;
let currentLength = 1;
while (isContain(nums, currentNum + 1)) {
currentNum += 1;
currentLength += 1;
}
maxLength = Math.max(maxLength, currentLength);
}
return maxLength;
};
function isContain(nums, target) {
for (let num of nums) {
if (num === target) {
return true;
}
}
return false;
}
3.2 哈希表解法
var longestConsecutive = function(nums) {
if (!nums || nums.length === 0) {
return 0;
}
let numSet = new Set(nums);
let maxLength = 0;
for (let num of nums) {
if (!numSet.has(num - 1)) {
let currentNum = num;
let currentLength = 1;
while (numSet.has(currentNum + 1)) {
currentNum += 1;
currentLength += 1;
}
maxLength = Math.max(maxLength, currentLength);
}
}
return maxLength;
};
- 知识点总结
4.1 连续序列
连续序列是指数组中相邻元素差为1的序列。例如 [1, 2, 3, 4] 就是一个连续序列。
4.2 哈希表
哈希表是一种基于键值对的数据结构,可以快速地进行查找、插入和删除操作。在解决这个问题时,我们使用哈希表来存储数组中的所有元素,这样可以快速地判断一个数是否在数组中。
4.3 时间复杂度和空间复杂度
- 暴力解法的时间复杂度为O(n^2),因为需要遍历每个元素并检查是否存在连续序列。
- 哈希表解法的时间复杂度为O(n),因为只需要遍历一次数组并进行哈希表的操作。
- 两种解法的空间复杂度都为O(n),因为需要使用哈希表来存储数组中的所有元素。
我的最长连续序列:Java和JavaScript解题指南(LeetCode 128)
目录
- 引言
- 题目简介
- 解题思路
- Java实现方案
- JavaScript实现方案
- 代码总结与优化
- 结语
1. 引言
在数据结构与算法的学习过程中,寻找数组中的连续序列长度是一项基础又关键的任务。LeetCode第128题“最长连续序列”正是锻炼我们该技巧的绝佳题目。本篇博客将详细讲解如何用Java和JavaScript解决此问题,适合新手理解和学习。
2. 题目简介
题目描述:
给定一个未排序的整数数组,找出最长的连续序列的长度。
示例:
输入:nums = [100, 4, 200, 1, 3, 2]
输出:4
解释:最长连续序列是 [1, 2, 3, 4],它的长度为4。
要求:
要求时间复杂度尽可能低,理想情况下是O(n)。
3. 解题思路
理解问题:
我们想找到数列中的连续数字序列,比如 [1, 2, 3, 4],无论数字在数组中的位置如何。
常见解法:
- **排序法(不推荐):**先对数组排序,再遍历一次找连续序列,复杂度O(n log n);
- 哈希集法(高效): 利用HashSet存储元素,并逐个扩展连续的序列,达到O(n)时间复杂度。
哈希集法的核心思想:
- 将数组元素插入HashSet,便于查找是否存在某个数字;
- 遍历数组元素,对于每个元素:
- 以该元素为中心,向左右扩展连续数字;
- 标记已访问的元素,避免重复计算;
- 维护最大连续序列长度。
4. Java实现方案
import java.util.HashSet;
import java.util.Set;
public class LongestConsecutiveSequence {
public int longestConsecutive(int[] nums) {
if (nums == null || nums.length == 0) return 0;
Set<Integer> numSet = new HashSet<>();
for (int num : nums) {
numSet.add(num);
}
int maxLength = 0;
for (int num : numSet) {
// 只扩展那些没有前驱数字(即,num - 1不存在)的数字
if (!numSet.contains(num - 1)) {
int currentNum = num;
int currentStreak = 1;
// 向后扩展连续序列
while (numSet.contains(currentNum + 1)) {
currentNum++;
currentStreak++;
}
maxLength = Math.max(maxLength, currentStreak);
}
}
return maxLength;
}
public static void main(String[] args) {
LongestConsecutiveSequence solution = new LongestConsecutiveSequence();
int[] arr = {100, 4, 200, 1, 3, 2};
System.out.println(solution.longestConsecutive(arr)); // 输出:4
}
}
解题要点:
- 利用HashSet提供O(1)查找;
- 避免重复扩展,只有起点(没有前驱的数字)开始扩展。
5. JavaScript实现方案
function longestConsecutive(nums) {
if (!nums || nums.length === 0) return 0;
const numSet = new Set(nums);
let maxLength = 0;
for (let num of numSet) {
// 只从序列的起点开始
if (!numSet.has(num - 1)) {
let currentNum = num;
let currentStreak = 1;
// 向后扩展
while (numSet.has(currentNum + 1)) {
currentNum++;
currentStreak++;
}
maxLength = Math.max(maxLength, currentStreak);
}
}
return maxLength;
}
// 示例
const nums = [100, 4, 200, 1, 3, 2];
console.log(longestConsecutive(nums)); // 输出:4
关键点:
- 同样利用Set存储元素;
- 只从没有前驱数字的元素开始扩展;
- 适合在JavaScript环境中快速实现。
6. 代码总结与优化
-
时间复杂度:
O(n),因为每个元素最多被访问两次(一次插入,一次扩展)。 -
空间复杂度:
O(n),用于存储HashSet。 -
优化建议:
- 可以减少HashSet的使用,提高空间利用率;
- 若数据中存在大量重复元素,预处理去重会提升效率。
7. 结语
通过本文,你应该已经掌握了如何利用HashSet在Java和JavaScript中高效地解决“最长连续序列”问题。关键在于利用元素的唯一性与查找速度,避免多余的重复计算,从而实现线性时间复杂度。
练习建议:
尝试用不同的数据结构或算法思路(如排序法,二分查找等)解决此题,或者扩展到更复杂的连续序列问题。不断实践与思考,提升你的算法能力!
祝你学习愉快,代码顺利!
力扣题解:128. 最长连续序列
目录
- 题目描述
- 解题思路
- 2.1 使用哈希集
- 2.2 时间复杂度分析
- Java 实现
- JavaScript 实现
- 总结
1. 题目描述
给定一个未排序的整数数组 nums
,返回最长连续序列的长度。
示例
-
输入:
nums = [100, 4, 200, 1, 3, 2]
- 输出:
4
- 解释: 最长连续序列是
[1, 2, 3, 4]
,其长度为4
。
- 输出:
-
输入:
nums = [0, 0]
- 输出:
1
- 输出:
提示
0 <= nums.length <= 10^4
-10^9 <= nums[i] <= 10^9
2. 解题思路
2.1 使用哈希集
为了找到最长的连续序列,我们可以使用哈希集(HashSet)来存储数组中的元素。具体步骤如下:
- 将所有元素插入哈希集。
- 遍历数组中的每个元素,检查它是否是一个连续序列的起始点(即
num - 1
不在哈希集中)。 - 如果是起始点,则从该点开始,向上查找连续的数字,直到找不到为止,并记录长度。
- 更新最长连续序列的长度。
这种方法的时间复杂度为 (O(n)),因为每个元素最多只会被访问两次(一次插入哈希集,一次查找)。
2.2 时间复杂度分析
- 时间复杂度: (O(n)),其中 (n) 是数组的长度。
- 空间复杂度: (O(n)),用于存储哈希集。
3. Java 实现
以下是 Java 的实现代码:
import java.util.HashSet;
public class LongestConsecutiveSequence {
public int longestConsecutive(int[] nums) {
HashSet<Integer> numSet = new HashSet<>();
for (int num : nums) {
numSet.add(num);
}
int longestStreak = 0;
for (int num : numSet) {
// 只从序列的起始点开始查找
if (!numSet.contains(num - 1)) {
int currentNum = num;
int currentStreak = 1;
while (numSet.contains(currentNum + 1)) {
currentNum++;
currentStreak++;
}
longestStreak = Math.max(longestStreak, currentStreak);
}
}
return longestStreak;
}
}
4. JavaScript 实现
以下是 JavaScript 的实现代码:
function longestConsecutive(nums) {
const numSet = new Set(nums);
let longestStreak = 0;
for (const num of numSet) {
// 只从序列的起始点开始查找
if (!numSet.has(num - 1)) {
let currentNum = num;
let currentStreak = 1;
while (numSet.has(currentNum + 1)) {
currentNum++;
currentStreak++;
}
longestStreak = Math.max(longestStreak, currentStreak);
}
}
return longestStreak;
}
5. 总结
在这篇博客中,我们讨论了力扣题目“128. 最长连续序列”的解法。我们首先介绍了题目的基本要求,然后分析了如何使用哈希集来有效地找到最长的连续序列。最后,我们提供了 Java 和 JavaScript 的实现代码。
通过使用哈希集,我们能够在 (O(n)) 的时间复杂度内解决这个问题,适合处理较大的输入数据。希望这篇博客能帮助你更好地理解这个问题及其解法!如果你有任何问题或想法,欢迎在评论区留言讨论。
好的,为你准备一篇关于 LeetCode 128. 最长连续序列的详细入门博客,包含 Java 和 JavaScript 的解法,并深入讲解算法思路和复杂度分析。
博客标题: LeetCode 128. 最长连续序列:新手入门指南 (Java & JavaScript)
目录:
- 引言:寻找最长的连续数字序列
- 题目描述
- 解题思路:哈希集合 (HashSet/Set)
- 3.1 为什么选择哈希集合?
- 3.2 算法步骤
- Java 代码实现
- 4.1 代码
- 4.2 代码解释
- JavaScript 代码实现
- 5.1 代码
- 5.2 代码解释
- 复杂度分析
- 6.1 时间复杂度
- 6.2 空间复杂度
- 其他解法(排序)及其分析
- 总结:掌握最长连续序列,提升算法思维!
博客正文:
1. 引言:寻找最长的连续数字序列
“最长连续序列”是 LeetCode 上一道经典的中等难度题目。它考察了你对集合数据结构的理解和应用,以及你解决问题的能力。掌握这道题的解法,对于你提升算法思维非常有帮助。
2. 题目描述
给定一个未排序的整数数组 nums
,找出最长连续序列的长度。
请你设计并实现时间复杂度为 O(n)
的算法解决此问题。
示例:
输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长连续序列是 [1, 2, 3, 4]。因此,其长度为 4。
输入:nums = [0,3,7,2,5,8,4,6,0,1]
输出:9
解释:最长连续序列是 [0, 1, 2, 3, 4, 5, 6, 7, 8]。因此,其长度为 9。
3. 解题思路:哈希集合 (HashSet/Set)
-
3.1 为什么选择哈希集合?
- 快速查找: 哈希集合(在 Java 中是
HashSet
,在 JavaScript 中是Set
)可以在平均情况下以 O(1) 的时间复杂度进行查找操作。这使得它非常适合用来判断一个数字是否在数组中存在。 - 去重: 哈希集合可以自动去除重复的数字,这简化了我们的算法。
- 快速查找: 哈希集合(在 Java 中是
-
3.2 算法步骤
- 创建一个哈希集合,并将数组
nums
中的所有数字添加到哈希集合中。 - 遍历数组
nums
。 - 对于每个数字
num
,检查num - 1
是否在哈希集合中。- 如果
num - 1
不在哈希集合中,这意味着num
是一个连续序列的起点。 - 从
num
开始,不断检查num + 1
是否在哈希集合中,直到找到一个不在哈希集合中的数字。 - 计算连续序列的长度。
- 更新最长连续序列的长度。
- 如果
- 返回最长连续序列的长度。
- 创建一个哈希集合,并将数组
4. Java 代码实现
-
4.1 代码
import java.util.HashSet; import java.util.Set; class Solution { public int longestConsecutive(int[] nums) { Set<Integer> numSet = new HashSet<>(); for (int num : nums) { numSet.add(num); } int longestStreak = 0; for (int num : nums) { if (!numSet.contains(num - 1)) { int currentNum = num; int currentStreak = 1; while (numSet.contains(currentNum + 1)) { currentNum += 1; currentStreak += 1; } longestStreak = Math.max(longestStreak, currentStreak); } } return longestStreak; } }
-
4.2 代码解释
Set<Integer> numSet = new HashSet<>();
: 创建一个HashSet
,用于存储数组中的数字。for (int num : nums)
: 遍历数组nums
,并将每个数字添加到HashSet
中。if (!numSet.contains(num - 1))
: 检查HashSet
中是否包含num - 1
。contains
方法的时间复杂度是 O(1) (平均情况)。while (numSet.contains(currentNum + 1))
: 从num
开始,不断检查HashSet
中是否包含currentNum + 1
。longestStreak = Math.max(longestStreak, currentStreak);
: 更新最长连续序列的长度。
5. JavaScript 代码实现
-
5.1 代码
function longestConsecutive(nums) { const numSet = new Set(nums); let longestStreak = 0; for (const num of nums) { if (!numSet.has(num - 1)) { let currentNum = num; let currentStreak = 1; while (numSet.has(currentNum + 1)) { currentNum += 1; currentStreak += 1; } longestStreak = Math.max(longestStreak, currentStreak); } } return longestStreak; }
-
5.2 代码解释
const numSet = new Set(nums);
: 创建一个Set
,用于存储数组中的数字。for (const num of nums)
: 遍历数组nums
。if (!numSet.has(num - 1))
: 检查Set
中是否包含num - 1
。has
方法的时间复杂度是 O(1) (平均情况)。while (numSet.has(currentNum + 1))
: 从num
开始,不断检查Set
中是否包含currentNum + 1
。longestStreak = Math.max(longestStreak, currentStreak);
: 更新最长连续序列的长度。
6. 复杂度分析
-
6.1 时间复杂度
- O(n),其中 n 是数组的长度。
- 将数字添加到哈希集合需要 O(n) 的时间。
- 遍历数组需要 O(n) 的时间。
- 虽然
while
循环看起来像是嵌套循环,但实际上每个数字最多只会被访问一次,因此总的时间复杂度仍然是 O(n)。
- O(n),其中 n 是数组的长度。
-
6.2 空间复杂度
- O(n),因为我们需要创建一个哈希集合来存储数组中的数字。 在最坏情况下,哈希集合需要存储数组中的所有元素。
7. 其他解法(排序)及其分析
另一种解法是先对数组进行排序,然后遍历排序后的数组,找到最长连续序列。
// Java 排序
import java.util.Arrays;
class Solution {
public int longestConsecutive(int[] nums) {
if (nums.length == 0) {
return 0;
}
Arrays.sort(nums);
int longestStreak = 1;
int currentStreak = 1;
for (int i = 1; i < nums.length; i++) {
if (nums[i] != nums[i - 1]) {
if (nums[i] == nums[i - 1] + 1) {
currentStreak += 1;
} else {
longestStreak = Math.max(longestStreak, currentStreak);
currentStreak = 1;
}
}
}
return Math.max(longestStreak, currentStreak);
}
}
// JavaScript 排序
function longestConsecutive(nums) {
if (nums.length === 0) {
return 0;
}
nums.sort((a, b) => a - b);
let longestStreak = 1;
let currentStreak = 1;
for (let i = 1; i < nums.length; i++) {
if (nums[i] !== nums[i - 1]) {
if (nums[i] === nums[i - 1] + 1) {
currentStreak += 1;
} else {
longestStreak = Math.max(longestStreak, currentStreak);
currentStreak = 1;
}
}
}
return Math.max(longestStreak, currentStreak);
}
- 时间复杂度: O(n log n),因为排序需要 O(n log n) 的时间。
- 空间复杂度: O(1) 或 O(n),取决于排序算法的空间复杂度。
8. 总结:掌握最长连续序列,提升算法思维!
“最长连续序列”是一道经典的算法题,通过学习这道题,你可以掌握哈希集合这种重要的数据结构,并学会如何使用它来解决实际问题。 希望这篇博客能帮助你入门算法和数据结构,并在你的编程之路上助你一臂之力! 继续学习和实践,你一定会成为一名优秀的程序员!
力扣 128 题:最长连续序列新手入门攻略
一、引言
在算法学习的道路上,力扣(LeetCode)是一个绝佳的试炼场。今天我们要攻克的是力扣第 128 题——最长连续序列。这道题要求我们在给定的整数数组中找出最长连续序列的长度,且算法的时间复杂度要控制在 O ( n ) O(n) O(n) 。接下来,我们会分别用 Java 和 JavaScript 实现解题思路,帮助新手更好地理解和掌握这道题。
二、题目描述
给定一个未排序的整数数组 nums
,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。请你设计并实现时间复杂度为
O
(
n
)
O(n)
O(n) 的算法解决此问题。
示例
- 示例 1:
- 输入:
nums = [100, 4, 200, 1, 3, 2]
- 输出:
4
- 解释:最长数字连续序列是
[1, 2, 3, 4]
,它的长度为4
。
- 输入:
- 示例 2:
- 输入:
nums = [0, 3, 7, 2, 5, 8, 4, 6, 0, 1]
- 输出:
9
- 解释:最长数字连续序列是
[0, 1, 2, 3, 4, 5, 6, 7, 8]
,它的长度为9
。
- 输入:
提示
0 <= nums.length <= 10^5
-10^9 <= nums[i] <= 10^9
三、解题思路
为了实现
O
(
n
)
O(n)
O(n) 的时间复杂度,我们可以使用哈希表(在 Java 中是 HashSet
,在 JavaScript 中是 Set
)来存储数组中的所有元素,这样可以在
O
(
1
)
O(1)
O(1) 的时间内判断一个元素是否存在。具体步骤如下:
- 将数组中的所有元素存入哈希表。
- 遍历数组中的每个元素
num
,如果num - 1
不在哈希表中,说明num
是一个连续序列的起始元素。 - 从
num
开始,不断检查num + 1
是否在哈希表中,直到找不到连续的元素为止,记录当前连续序列的长度。 - 重复步骤 2 和 3,更新最长连续序列的长度。
四、Java 实现
4.1 代码示例
import java.util.HashSet;
import java.util.Set;
public class LongestConsecutiveSequence {
public int longestConsecutive(int[] nums) {
// 创建一个 HashSet 用于存储数组中的元素
Set<Integer> numSet = new HashSet<>();
for (int num : nums) {
numSet.add(num);
}
int longestStreak = 0;
// 遍历数组中的每个元素
for (int num : nums) {
// 如果 num - 1 不在集合中,说明 num 是一个连续序列的起始元素
if (!numSet.contains(num - 1)) {
int currentNum = num;
int currentStreak = 1;
// 不断检查 num + 1 是否在集合中
while (numSet.contains(currentNum + 1)) {
currentNum += 1;
currentStreak += 1;
}
// 更新最长连续序列的长度
longestStreak = Math.max(longestStreak, currentStreak);
}
}
return longestStreak;
}
public static void main(String[] args) {
LongestConsecutiveSequence solution = new LongestConsecutiveSequence();
int[] nums = {100, 4, 200, 1, 3, 2};
int result = solution.longestConsecutive(nums);
System.out.println("最长连续序列的长度是: " + result);
}
}
4.2 代码解释
- 创建哈希表:使用
HashSet
存储数组中的所有元素,方便后续快速查找。 - 遍历数组:对于每个元素
num
,检查num - 1
是否在哈希表中,如果不在,说明num
是一个连续序列的起始元素。 - 计算连续序列长度:从
num
开始,不断检查num + 1
是否在哈希表中,更新当前连续序列的长度。 - 更新最长连续序列长度:每次找到一个连续序列后,更新最长连续序列的长度。
4.3 复杂度分析
- 时间复杂度: O ( n ) O(n) O(n) ,因为每个元素最多被访问两次(一次是添加到哈希表,一次是检查连续序列)。
- 空间复杂度: O ( n ) O(n) O(n) ,主要用于存储哈希表中的元素。
五、JavaScript 实现
5.1 代码示例
function longestConsecutive(nums) {
// 创建一个 Set 用于存储数组中的元素
const numSet = new Set(nums);
let longestStreak = 0;
// 遍历数组中的每个元素
for (let num of numSet) {
// 如果 num - 1 不在集合中,说明 num 是一个连续序列的起始元素
if (!numSet.has(num - 1)) {
let currentNum = num;
let currentStreak = 1;
// 不断检查 num + 1 是否在集合中
while (numSet.has(currentNum + 1)) {
currentNum += 1;
currentStreak += 1;
}
// 更新最长连续序列的长度
longestStreak = Math.max(longestStreak, currentStreak);
}
}
return longestStreak;
}
const nums = [100, 4, 200, 1, 3, 2];
const result = longestConsecutive(nums);
console.log("最长连续序列的长度是: ", result);
5.2 代码解释
- 创建哈希表:使用
Set
存储数组中的所有元素。 - 遍历数组:对于每个元素
num
,检查num - 1
是否在Set
中,如果不在,说明num
是一个连续序列的起始元素。 - 计算连续序列长度:从
num
开始,不断检查num + 1
是否在Set
中,更新当前连续序列的长度。 - 更新最长连续序列长度:每次找到一个连续序列后,更新最长连续序列的长度。
5.3 复杂度分析
- 时间复杂度: O ( n ) O(n) O(n) ,每个元素最多被访问两次。
- 空间复杂度:
O
(
n
)
O(n)
O(n) ,主要用于存储
Set
中的元素。
六、总结
通过本题的学习,我们掌握了使用哈希表来解决最长连续序列问题的方法,并且实现了 O ( n ) O(n) O(n) 的时间复杂度。无论是 Java 还是 JavaScript ,核心思路都是一致的。希望这篇博客能帮助新手朋友们更好地理解和解决这道题目,在算法学习的道路上更进一步。
七、参考资料
- 力扣(LeetCode)官方网站
- 《算法导论》相关章节
【新手入门】LeetCode 128. 最长连续序列:Java & JavaScript 双解法详解
目录
1. 题目描述
给定一个未排序的整数数组 nums
,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。要求算法的时间复杂度为 O(n)。
示例:
输入: nums = [100,4,200,1,3,2]
输出: 4
解释: 最长连续序列是 [1, 2, 3, 4],长度为 4。
2. 解题思路分析
2.1 哈希集合法(最优解)
- 核心思想:利用哈希集合(
HashSet
)快速查找元素,避免排序。 - 步骤:
- 将所有数字存入哈希集合。
- 遍历集合,对于每个数字
num
,检查num-1
是否存在于集合中:- 如果不存在,则
num
是一个连续序列的起点。 - 从
num
开始,逐个检查num+1
、num+2
… 是否在集合中,统计连续序列长度。
- 如果不存在,则
- 更新全局最大长度。
- 时间复杂度:O(n)(每个元素最多被访问两次)。
- 空间复杂度:O(n)。
2.2 排序法(次优解)
- 核心思想:先排序数组,再遍历统计连续序列长度。
- 缺点:时间复杂度为 O(n log n),不满足题目要求,但易于理解。
- 步骤:
- 排序数组。
- 遍历数组,跳过重复元素,统计连续递增序列的长度。
3. Java 代码实现
方法一:哈希集合法
import java.util.*;
class Solution {
public int longestConsecutive(int[] nums) {
Set<Integer> set = new HashSet<>();
for (int num : nums) {
set.add(num);
}
int maxLength = 0;
for (int num : set) {
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;
}
}
方法二:排序法
import java.util.Arrays;
class Solution {
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]) { // 跳过重复元素
if (nums[i] == nums[i - 1] + 1) {
currentLength++;
} else {
maxLength = Math.max(maxLength, currentLength);
currentLength = 1;
}
}
}
return Math.max(maxLength, currentLength);
}
}
4. JavaScript 代码实现
方法一:哈希集合法
function longestConsecutive(nums) {
const set = new Set(nums);
let maxLength = 0;
for (const num of set) {
if (!set.has(num - 1)) { // 确保是序列起点
let currentNum = num;
let currentLength = 1;
while (set.has(currentNum + 1)) {
currentNum++;
currentLength++;
}
maxLength = Math.max(maxLength, currentLength);
}
}
return maxLength;
}
方法二:排序法
function longestConsecutive(nums) {
if (nums.length === 0) return 0;
nums.sort((a, b) => a - b);
let maxLength = 1;
let currentLength = 1;
for (let i = 1; i < nums.length; i++) {
if (nums[i] !== nums[i - 1]) { // 跳过重复元素
if (nums[i] === nums[i - 1] + 1) {
currentLength++;
} else {
maxLength = Math.max(maxLength, currentLength);
currentLength = 1;
}
}
}
return Math.max(maxLength, currentLength);
}
5. 复杂度分析
方法 | 时间复杂度 | 空间复杂度 | 适用场景 |
---|---|---|---|
哈希集合法 | O(n) | O(n) | 满足题目要求,最优解 |
排序法 | O(n log n) | O(1) 或 O(n) | 不满足题目要求,但易懂 |
6. 边界条件与注意事项
- 空数组:直接返回
0
。 - 重复元素:需要跳过重复数字(如
[1, 2, 2, 3]
的最长序列是[1, 2, 3]
)。 - 负数处理:哈希集合法天然支持负数(如
[-1, 0, 1]
)。
7. 总结
-
面试推荐:哈希集合法(O(n) 时间复杂度)。
-
关键点:
- 使用哈希集合避免排序。
- 确保只从连续序列的起点开始统计(即
num-1
不在集合中)。
-
代码模板:
// Java 哈希集合法 Set<Integer> set = new HashSet<>(); for (int num : nums) set.add(num); for (int num : set) { if (!set.contains(num - 1)) { // 统计连续序列长度 } }
// JavaScript 哈希集合法 const set = new Set(nums); for (const num of set) { if (!set.has(num - 1)) { // 统计连续序列长度 } }
掌握这道题,你就能高效解决数组中的连续序列问题! 🚀
最长连续序列:Java与JavaScript的高效解法
目录
- 问题描述与示例
- 暴力解法与优化思路
- 哈希表优化法详解
- Java代码实现
- JavaScript代码实现
- 复杂度分析
- 常见问题解答
- 进阶思考与扩展
1. 问题描述与示例
题目:给定一个无序的整数数组,找出其中最长连续序列的长度。
要求:
- 连续序列的元素可以不连续出现在数组中,但数值必须连续。
- 例如,
[4,3,2,1]
的最长连续序列是4
(1-2-3-4)。
示例:
- 输入:
[100, 4, 200, 1, 3, 2]
- 输出:
4
- 解释:最长连续序列是
1→2→3→4
。
2. 暴力解法与优化思路
暴力解法
遍历每个元素,尝试向左右延伸寻找连续序列:
// Java暴力解法(时间复杂度 O(n²))
public int longestConsecutive(int[] nums) {
Set<Integer> numSet = new HashSet<>();
for (int num : nums) {
numSet.add(num);
}
int longest = 0;
for (int num : numSet) {
if (!numSet.contains(num - 1)) { // 只从序列起点开始延伸
int currentNum = num;
int currentLength = 1;
while (numSet.contains(currentNum + 1)) {
currentNum += 1;
currentLength += 1;
}
longest = Math.max(longest, currentLength);
}
}
return longest;
}
问题:时间复杂度为 O(n²),当数组长度较大时(如 10^5
)会超时。
3. 哈希表优化法详解
核心思想
利用哈希表(HashSet)记录所有元素,然后:
- 仅从序列的起点开始延伸:
- 如果
num-1
不在哈希表中,则num
是某个连续序列的起点。
- 如果
- 向右延伸:
- 检查
num+1
,num+2
, … 是否在哈希表中,直到无法延伸为止。
- 检查
步骤分解
- 将所有元素存入哈希表。
- 遍历哈希表中的每个元素:
- 如果该元素是某个序列的起点(即
num-1
不在哈希表中),则开始向右延伸。 - 统计当前序列的长度,并更新全局最大值。
- 如果该元素是某个序列的起点(即
关键优化:
- 仅处理起点元素:避免重复计算同一序列的多个中间元素。
- 时间复杂度降为 O(n):每个元素最多被访问两次(作为起点或中间元素)。
4. Java代码实现
import java.util.HashSet;
import java.util.Set;
public class LongestConsecutiveSequence {
public int longestConsecutive(int[] nums) {
Set<Integer> numSet = new HashSet<>();
for (int num : nums) {
numSet.add(num);
}
int longestStreak = 0;
for (int num : numSet) {
// 只处理序列的起点
if (!numSet.contains(num - 1)) {
int currentNum = num;
int currentStreak = 1;
while (numSet.contains(currentNum + 1)) {
currentNum += 1;
currentStreak += 1;
}
longestStreak = Math.max(longestStreak, currentStreak);
}
}
return longestStreak;
}
}
关键点:
- 起点判断:通过
numSet.contains(num - 1)
确定是否为起点。 - 延伸过程:通过循环检查
currentNum + 1
是否存在。
5. JavaScript代码实现
/**
* @param {number[]} nums
* @return {number}
*/
var longestConsecutive = function(nums) {
const numSet = new Set(nums);
let longestStreak = 0;
for (const num of numSet) {
// 只处理序列的起点
if (!numSet.has(num - 1)) {
let currentNum = num;
let currentStreak = 1;
while (numSet.has(currentNum + 1)) {
currentNum += 1;
currentStreak += 1;
}
longestStreak = Math.max(longestStreak, currentStreak);
}
}
return longestStreak;
};
关键点:
- Set的使用:JavaScript的
Set
对象支持快速的has
操作(时间复杂度 O(1))。 - 起点判断:通过
!numSet.has(num - 1)
确保只处理起点。
6. 复杂度分析
时间复杂度
- 哈希表优化法:O(n)
- 遍历数组存入哈希表:O(n)。
- 遍历哈希表并延伸:每个元素最多被访问两次(起点和中间元素),总时间 O(n)。
空间复杂度
- O(n):哈希表存储所有元素。
7. 常见问题解答
Q1:为什么只处理起点元素?
- 因为非起点元素属于某个已存在的序列,重复计算会导致时间浪费。
Q2:如何处理重复元素?
- 哈希表自动去重,无需额外处理。
Q3:输入为空数组时如何处理?
- 返回
0
,代码中已隐含处理。
8. 进阶思考与扩展
其他可能的解法
- 排序法:
- 将数组排序,时间复杂度 O(n log n)。
- 遍历排序后的数组,统计连续序列长度。
缺点:时间复杂度高于哈希表法。
应用场景
- 数据分析中的连续事件检测(如用户登录时间序列)。
- 游戏开发中的连续得分奖励判定。
总结
通过哈希表优化法,我们成功将时间复杂度从 O(n²) 降至 O(n),解决了大规模数据的性能问题。无论是 Java 还是 JavaScript,核心逻辑一致,仅语法细节不同。掌握这一技巧后,可以轻松应对类似问题(如最长递增子序列、连续子数组的最大和)。
推荐阅读:
- LeetCode 题目:300. 最长递增子序列
- 算法学习:哈希表的其他应用场景(如两数之和、字母异位词分组)。
LeetCode 128. 最长连续序列:Java与JavaScript哈希集解法详解|新手必学算法技巧
目录
一、问题描述
给定一个未排序的整数数组 nums
,找出数字连续的最长序列的长度。要求算法的时间复杂度为 O(n)。
示例:
输入: [100,4,200,1,3,2]
输出: 4
解释: 最长连续序列是 [1,2,3,4]
关键要求:
- 时间复杂度必须为 O(n)
- 数组可能包含重复数字
- 需要处理空数组的情况
二、核心思路:哈希集合的巧妙应用
暴力法 vs 优化法对比
方法 | 核心思路 | 时间复杂度 | 空间复杂度 |
---|---|---|---|
排序遍历法 | 先排序后查找连续序列 | O(n log n) | O(1) |
哈希集法 | 利用集合快速查询相邻元素存在性 | O(n) | O(n) |
算法步骤
- 哈希集存储:将所有数字存入哈希集合
- 寻找序列起点:遍历集合,当发现
num-1
不存在时,说明num
是某个序列的起点 - 扩展序列:从起点开始不断查找
num+1
是否存在,计算序列长度 - 更新最大值:记录遍历过程中的最大序列长度
三、Java解法详解
完整代码实现
import java.util.HashSet;
class Solution {
public int longestConsecutive(int[] nums) {
HashSet<Integer> numSet = new HashSet<>();
for (int num : nums) {
numSet.add(num);
}
int maxStreak = 0;
for (int num : numSet) {
// 只有当num是序列起点时才进行扩展
if (!numSet.contains(num - 1)) {
int currentNum = num;
int currentStreak = 1;
// 向右扩展连续序列
while (numSet.contains(currentNum + 1)) {
currentNum++;
currentStreak++;
}
maxStreak = Math.max(maxStreak, currentStreak);
}
}
return maxStreak;
}
}
关键代码解析
- 哈希集初始化:
numSet
存储所有唯一数字 - 序列起点判断:
numSet.contains(num - 1)
为false时触发扩展 - 序列扩展逻辑:通过
while
循环查找连续递增数字
测试案例
public static void main(String[] args) {
Solution sol = new Solution();
int[] test1 = {100,4,200,1,3,2};
System.out.println(sol.longestConsecutive(test1)); // 输出4
int[] test2 = {0,3,7,2,5,8,4,6,0,1};
System.out.println(sol.longestConsecutive(test2)); // 输出9
}
四、JavaScript解法详解
完整代码实现
const longestConsecutive = (nums) => {
const numSet = new Set(nums);
let maxStreak = 0;
for (const num of numSet) {
// 检查是否为序列起点
if (!numSet.has(num - 1)) {
let currentNum = num;
let currentStreak = 1;
// 向右扩展连续序列
while (numSet.has(currentNum + 1)) {
currentNum++;
currentStreak++;
}
maxStreak = Math.max(maxStreak, currentStreak);
}
}
return maxStreak;
};
关键代码解析
- Set初始化:
new Set(nums)
自动去重 - 序列扩展逻辑:与Java实现逻辑完全一致
- 循环优化:直接遍历Set而非原数组,避免重复处理
浏览器测试
console.log(longestConsecutive([100,4,200,1,3,2])); // 4
console.log(longestConsecutive([0,3,7,2,5,8,4,6,0,1])); // 9
五、复杂度分析
时间复杂度:O(n)
- 每个元素最多被访问两次:
- 第一次加入集合
- 第二次作为序列扩展的起点或中间节点
空间复杂度:O(n)
- 哈希集合存储所有元素
六、Java与JavaScript实现对比
特性 | Java | JavaScript |
---|---|---|
集合初始化 | 需要循环添加元素 | new Set(nums) 一步完成 |
空集合处理 | 返回0自动处理 | 同左 |
循环方式 | 增强for循环遍历Set | for...of 遍历Set |
性能优化 | 遍历Set而非原数组 | 同左 |
七、常见错误与解决方法
错误1:直接遍历原数组
// 错误示例:遍历原数组可能重复处理相同数字
for (int num : nums) { // 当数组有重复元素时会重复处理
if (!numSet.contains(num - 1)) {
// ...
}
}
解决方法:必须遍历哈希集合 numSet
错误2:未处理空输入
// 当nums为空数组时,返回0是正确的
console.log(longestConsecutive([])); // 0
错误3:使用数组includes方法(仅JS)
// 错误:数组的includes方法时间复杂度是O(n)
if (nums.includes(num - 1)) { /* ... */ }
解决方法:必须使用Set的has
方法(O(1)时间复杂度)
八、举一反三练习
- 变形题:674. 最长连续递增序列(要求元素连续递增)
- 进阶题:剑指 Offer 51. 数组中的逆序对(分治算法应用)
- 系统设计:如果输入数据无法一次性加载到内存,如何分布式处理?
学习建议:
尝试用并查集(Union-Find)数据结构解决此题,比较不同解法的效率差异。
掌握这道题的关键在于理解哈希集合的快速查询特性。通过寻找序列起点并向右扩展的策略,我们能够在线性时间复杂度内解决问题。这种思路在处理需要快速判断元素存在性的问题时非常有效,值得举一反三应用到其他算法题目中! 🚀
力扣128题详解:最长连续序列(Java & JavaScript 双语言实现)
目录
1. 问题描述 {#1}
给定一个未排序的整数数组 nums
,找到数字连续的最长序列的长度。要求算法的时间复杂度为 O(n)。
示例:
输入: nums = [100,4,200,1,3,2]
输出: 4(最长连续序列为 [1,2,3,4])
提示:
- 数组可能包含重复元素
- 结果不要求序列元素在原数组中连续
2. 核心思路 {#2}
关键点
- 哈希集去重:用哈希表(HashSet/Set)存储数组元素,去重且支持 O(1) 查询。
- 寻找序列起点:若
num-1
不在集合中,则num
是某个连续序列的起点。 - 向后扩展序列:从起点
num
开始,依次检查num+1
、num+2
是否在集合中,计算长度。
3. 解法:哈希集优化法 {#3}
步骤
- 去重存储:将所有元素存入哈希集。
- 遍历元素:检查每个元素是否为某个连续序列的起点。
- 扩展序列:若为起点,向后查找连续元素,统计最长长度。
4. 复杂度分析 {#4}
指标 | 复杂度 | 说明 |
---|---|---|
时间复杂度 | O(n) | 每个元素最多被访问两次 |
空间复杂度 | O(n) | 哈希集存储所有元素 |
5. 代码实现 {#5}
Java实现
import java.util.HashSet;
import java.util.Set;
public class Solution {
public int longestConsecutive(int[] nums) {
if (nums == null || nums.length == 0) return 0;
Set<Integer> set = new HashSet<>();
for (int num : nums) set.add(num);
int longest = 0;
for (int num : nums) {
if (!set.contains(num - 1)) { // 当前元素是起点
int current = num;
int length = 1;
while (set.contains(current + 1)) {
current++;
length++;
}
longest = Math.max(longest, length);
}
}
return longest;
}
}
JavaScript实现
function longestConsecutive(nums) {
if (nums.length === 0) return 0;
const set = new Set(nums);
let longest = 0;
for (const num of set) {
if (!set.has(num - 1)) { // 当前元素是起点
let current = num;
let length = 1;
while (set.has(current + 1)) {
current++;
length++;
}
longest = Math.max(longest, length);
}
}
return longest;
}
关键点解释:
- 去重处理:Java 使用
HashSet
,JavaScript 使用new Set()
。 - 避免重复计算:仅当元素是起点时才向后扩展,确保每个元素至多被访问两次。
6. 测试用例 {#6}
Java测试
public static void main(String[] args) {
int[] nums = {100, 4, 200, 1, 3, 2};
Solution solution = new Solution();
System.out.println(solution.longestConsecutive(nums)); // 输出4
}
JavaScript测试
console.log(longestConsecutive([0, 3, 7, 2, 5, 8, 4, 6, 0, 1])); // 输出9
7. 总结 {#7}
- 核心技巧:利用哈希集的 O(1) 查询特性,快速判断连续元素是否存在。
- 性能优化:通过仅处理序列起点,避免重复遍历,确保时间复杂度为 O(n)。
- 扩展思考:若需更高性能,可结合并查集(Union-Find),但代码复杂度较高。
参考资料
Java HashSet解法与复杂度分析
并查集实现思路与代码示例
JavaScript Set特性与遍历方法