【算法入门】力扣题128:最长连续序列的Java与JavaScript解法|LeetCode 128. 最长连续序列:Java与JavaScript哈希集解法详解|新手必学算法技巧|

在这里插入图片描述
https://leetcode.cn/problems/longest-consecutive-sequence/description/?envType=study-plan-v2&envId=top-100-liked

参考答案

【新手入门】LeetCode 128. 最长连续序列:Java & JavaScript双语言详解

目录

  1. 题目描述
  2. 核心概念解析
    • 2.1 什么是连续序列?
    • 2.2 解题关键思路
  3. Java实现
    • 3.1 哈希集合法(最优解)
    • 3.2 排序法(次优解)
  4. JavaScript实现
    • 4.1 哈希集合法
    • 4.2 排序法
  5. 复杂度分析
  6. 边界条件与注意事项
  7. 总结与拓展

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 解题关键思路

  1. 方法一:哈希集合法(最优)
    • 使用哈希集合存储所有数字,快速判断某个数是否存在。
    • 遍历数组,对每个数检查它是否是连续序列的起点(即 num-1 不在集合中),然后向后扩展序列。
  2. 方法二:排序法(次优)
    • 先排序数组,然后遍历统计连续序列的长度(不满足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. 边界条件与注意事项

  1. 空数组:直接返回 0
  2. 重复数字:哈希集合法自动去重,排序法需跳过重复项(如 [1,2,0,1])。
  3. 负数处理:哈希法无需特殊处理,排序法需正确比较大小。

7. 总结与拓展

📌 下期预告:《LeetCode 674:如何高效处理连续递增序列?》
🔗 相关推荐LeetCode 哈希表专题

如果有帮助,请点赞收藏支持! 🚀


博客标题:【算法入门】力扣题128:最长连续序列的Java与JavaScript解法

目录

  1. 引言
  2. 问题描述
  3. 算法分析
  4. Java解法
    • 4.1 暴力解法
    • 4.2 排序+双指针解法
    • 4.3 哈希表+排序解法
  5. JavaScript解法
    • 5.1 暴力解法
    • 5.2 排序+双指针解法
    • 5.3 哈希表+排序解法
  6. 总结
  7. 参考文献

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. 引言
  2. 问题分析
  3. Java实现
    1. 算法思路
    2. 代码实现
  4. JavaScript实现
    1. 算法思路
    2. 代码实现
  5. 总结

1. 引言

最长连续序列问题是一个经典的编程问题,要求找出给定数组中最长的连续序列的长度。本文将分别使用Java和JavaScript两种编程语言来解答这个问题,并详细解释其实现思路和代码。

2. 问题分析

给定一个未排序的整数数组,找出最长连续序列的长度。例如,对于数组 [100, 4, 200, 1, 3, 2],最长连续序列是 [1, 2, 3, 4],其长度为4。

3. Java实现

3.1 算法思路
  1. 使用HashSet存储数组中的所有元素,以便快速检查元素是否存在。
  2. 遍历数组,对于每个元素,检查它是否是某个连续序列的开始。
  3. 如果是,则递增地检查后续元素,直到序列结束。
  4. 更新最长连续序列的长度。
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. 最长连续序列

目录:

  1. 问题描述

  2. Java解答
    2.1 暴力解法
    2.2 哈希表解法

  3. JavaScript解答
    3.1 暴力解法
    3.2 哈希表解法

  4. 知识点总结
    4.1 连续序列
    4.2 哈希表
    4.3 时间复杂度和空间复杂度

  5. 问题描述
    力扣题 128. 最长连续序列要求给定一个未排序的整数数组 nums,找出其中最长连续元素序列的长度。

连续序列是指数组中相邻元素差为1的序列。例如,输入 [100, 4, 200, 1, 3, 2],输出 4,因为最长的连续序列是 [1, 2, 3, 4]。

  1. 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;
}
  1. 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;
};
  1. 知识点总结

4.1 连续序列
连续序列是指数组中相邻元素差为1的序列。例如 [1, 2, 3, 4] 就是一个连续序列。

4.2 哈希表
哈希表是一种基于键值对的数据结构,可以快速地进行查找、插入和删除操作。在解决这个问题时,我们使用哈希表来存储数组中的所有元素,这样可以快速地判断一个数是否在数组中。

4.3 时间复杂度和空间复杂度

  • 暴力解法的时间复杂度为O(n^2),因为需要遍历每个元素并检查是否存在连续序列。
  • 哈希表解法的时间复杂度为O(n),因为只需要遍历一次数组并进行哈希表的操作。
  • 两种解法的空间复杂度都为O(n),因为需要使用哈希表来存储数组中的所有元素。

我的最长连续序列:Java和JavaScript解题指南(LeetCode 128)

目录

  1. 引言
  2. 题目简介
  3. 解题思路
  4. Java实现方案
  5. JavaScript实现方案
  6. 代码总结与优化
  7. 结语

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)时间复杂度。

哈希集法的核心思想:

  1. 将数组元素插入HashSet,便于查找是否存在某个数字;
  2. 遍历数组元素,对于每个元素:
    • 以该元素为中心,向左右扩展连续数字;
    • 标记已访问的元素,避免重复计算;
  3. 维护最大连续序列长度。

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. 最长连续序列

目录

  1. 题目描述
  2. 解题思路
    • 2.1 使用哈希集
    • 2.2 时间复杂度分析
  3. Java 实现
  4. JavaScript 实现
  5. 总结

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)来存储数组中的元素。具体步骤如下:

  1. 将所有元素插入哈希集。
  2. 遍历数组中的每个元素,检查它是否是一个连续序列的起始点(即 num - 1 不在哈希集中)。
  3. 如果是起始点,则从该点开始,向上查找连续的数字,直到找不到为止,并记录长度。
  4. 更新最长连续序列的长度。

这种方法的时间复杂度为 (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)

目录:

  1. 引言:寻找最长的连续数字序列
  2. 题目描述
  3. 解题思路:哈希集合 (HashSet/Set)
    • 3.1 为什么选择哈希集合?
    • 3.2 算法步骤
  4. Java 代码实现
    • 4.1 代码
    • 4.2 代码解释
  5. JavaScript 代码实现
    • 5.1 代码
    • 5.2 代码解释
  6. 复杂度分析
    • 6.1 时间复杂度
    • 6.2 空间复杂度
  7. 其他解法(排序)及其分析
  8. 总结:掌握最长连续序列,提升算法思维!

博客正文:

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) 的时间复杂度进行查找操作。这使得它非常适合用来判断一个数字是否在数组中存在。
    • 去重: 哈希集合可以自动去除重复的数字,这简化了我们的算法。
  • 3.2 算法步骤

    1. 创建一个哈希集合,并将数组 nums 中的所有数字添加到哈希集合中。
    2. 遍历数组 nums
    3. 对于每个数字 num,检查 num - 1 是否在哈希集合中。
      • 如果 num - 1 不在哈希集合中,这意味着 num 是一个连续序列的起点。
      • num 开始,不断检查 num + 1 是否在哈希集合中,直到找到一个不在哈希集合中的数字。
      • 计算连续序列的长度。
      • 更新最长连续序列的长度。
    4. 返回最长连续序列的长度。

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 - 1contains 方法的时间复杂度是 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 - 1has 方法的时间复杂度是 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)。
  • 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) 的时间内判断一个元素是否存在。具体步骤如下:

  1. 将数组中的所有元素存入哈希表。
  2. 遍历数组中的每个元素 num ,如果 num - 1 不在哈希表中,说明 num 是一个连续序列的起始元素。
  3. num 开始,不断检查 num + 1 是否在哈希表中,直到找不到连续的元素为止,记录当前连续序列的长度。
  4. 重复步骤 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 代码解释

  1. 创建哈希表:使用 HashSet 存储数组中的所有元素,方便后续快速查找。
  2. 遍历数组:对于每个元素 num ,检查 num - 1 是否在哈希表中,如果不在,说明 num 是一个连续序列的起始元素。
  3. 计算连续序列长度:从 num 开始,不断检查 num + 1 是否在哈希表中,更新当前连续序列的长度。
  4. 更新最长连续序列长度:每次找到一个连续序列后,更新最长连续序列的长度。

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 代码解释

  1. 创建哈希表:使用 Set 存储数组中的所有元素。
  2. 遍历数组:对于每个元素 num ,检查 num - 1 是否在 Set 中,如果不在,说明 num 是一个连续序列的起始元素。
  3. 计算连续序列长度:从 num 开始,不断检查 num + 1 是否在 Set 中,更新当前连续序列的长度。
  4. 更新最长连续序列长度:每次找到一个连续序列后,更新最长连续序列的长度。

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. 题目描述
  2. 解题思路分析
    • 2.1 哈希集合法(最优解)
    • 2.2 排序法(次优解)
  3. Java 代码实现
  4. JavaScript 代码实现
  5. 复杂度分析
  6. 边界条件与注意事项
  7. 总结

1. 题目描述

给定一个未排序的整数数组 nums,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。要求算法的时间复杂度为 O(n)

示例

输入: nums = [100,4,200,1,3,2]
输出: 4
解释: 最长连续序列是 [1, 2, 3, 4],长度为 4。

2. 解题思路分析

2.1 哈希集合法(最优解)

  • 核心思想:利用哈希集合(HashSet)快速查找元素,避免排序。
  • 步骤
    1. 将所有数字存入哈希集合。
    2. 遍历集合,对于每个数字 num,检查 num-1 是否存在于集合中:
      • 如果不存在,则 num 是一个连续序列的起点。
      • num 开始,逐个检查 num+1num+2… 是否在集合中,统计连续序列长度。
    3. 更新全局最大长度。
  • 时间复杂度:O(n)(每个元素最多被访问两次)。
  • 空间复杂度:O(n)。

2.2 排序法(次优解)

  • 核心思想:先排序数组,再遍历统计连续序列长度。
  • 缺点:时间复杂度为 O(n log n),不满足题目要求,但易于理解。
  • 步骤
    1. 排序数组。
    2. 遍历数组,跳过重复元素,统计连续递增序列的长度。

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. 边界条件与注意事项

  1. 空数组:直接返回 0
  2. 重复元素:需要跳过重复数字(如 [1, 2, 2, 3] 的最长序列是 [1, 2, 3])。
  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的高效解法

目录

  1. 问题描述与示例
  2. 暴力解法与优化思路
  3. 哈希表优化法详解
  4. Java代码实现
  5. JavaScript代码实现
  6. 复杂度分析
  7. 常见问题解答
  8. 进阶思考与扩展

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)记录所有元素,然后:

  1. 仅从序列的起点开始延伸
    • 如果 num-1 不在哈希表中,则 num 是某个连续序列的起点。
  2. 向右延伸
    • 检查 num+1, num+2, … 是否在哈希表中,直到无法延伸为止。

步骤分解

  1. 将所有元素存入哈希表。
  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. 进阶思考与扩展

其他可能的解法

  • 排序法
    1. 将数组排序,时间复杂度 O(n log n)。
    2. 遍历排序后的数组,统计连续序列长度。
      缺点:时间复杂度高于哈希表法。

应用场景

  • 数据分析中的连续事件检测(如用户登录时间序列)。
  • 游戏开发中的连续得分奖励判定。

总结

通过哈希表优化法,我们成功将时间复杂度从 O(n²) 降至 O(n),解决了大规模数据的性能问题。无论是 Java 还是 JavaScript,核心逻辑一致,仅语法细节不同。掌握这一技巧后,可以轻松应对类似问题(如最长递增子序列、连续子数组的最大和)。

推荐阅读

  • LeetCode 题目:300. 最长递增子序列
  • 算法学习:哈希表的其他应用场景(如两数之和、字母异位词分组)。


LeetCode 128. 最长连续序列:Java与JavaScript哈希集解法详解|新手必学算法技巧

目录

  1. 问题描述
  2. 核心思路
  3. Java解法详解
  4. JavaScript解法详解
  5. 复杂度分析
  6. 两种语言实现对比
  7. 常见错误与解决方法
  8. 举一反三练习

一、问题描述

给定一个未排序的整数数组 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)

算法步骤

  1. 哈希集存储:将所有数字存入哈希集合
  2. 寻找序列起点:遍历集合,当发现num-1不存在时,说明num是某个序列的起点
  3. 扩展序列:从起点开始不断查找num+1是否存在,计算序列长度
  4. 更新最大值:记录遍历过程中的最大序列长度

三、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;
    }
}

关键代码解析

  1. 哈希集初始化numSet存储所有唯一数字
  2. 序列起点判断numSet.contains(num - 1)为false时触发扩展
  3. 序列扩展逻辑:通过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;
};

关键代码解析

  1. Set初始化new Set(nums)自动去重
  2. 序列扩展逻辑:与Java实现逻辑完全一致
  3. 循环优化:直接遍历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实现对比

特性JavaJavaScript
集合初始化需要循环添加元素new Set(nums)一步完成
空集合处理返回0自动处理同左
循环方式增强for循环遍历Setfor...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)时间复杂度)


八、举一反三练习

  1. 变形题674. 最长连续递增序列(要求元素连续递增)
  2. 进阶题剑指 Offer 51. 数组中的逆序对(分治算法应用)
  3. 系统设计:如果输入数据无法一次性加载到内存,如何分布式处理?

学习建议
尝试用并查集(Union-Find)数据结构解决此题,比较不同解法的效率差异。


掌握这道题的关键在于理解哈希集合的快速查询特性。通过寻找序列起点并向右扩展的策略,我们能够在线性时间复杂度内解决问题。这种思路在处理需要快速判断元素存在性的问题时非常有效,值得举一反三应用到其他算法题目中! 🚀



力扣128题详解:最长连续序列(Java & JavaScript 双语言实现)

目录

  1. 问题描述
  2. 核心思路
  3. 解法:哈希集优化法
  4. 复杂度分析
  5. 代码实现
  6. 测试用例
  7. 总结

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+1num+2 是否在集合中,计算长度。

3. 解法:哈希集优化法 {#3}

步骤

  1. 去重存储:将所有元素存入哈希集。
  2. 遍历元素:检查每个元素是否为某个连续序列的起点。
  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特性与遍历方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南北极之间

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值