力扣128. 最长连续序列

题目描述:

128. 最长连续序列

难度 中等

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

请你设计并实现时间复杂度为 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

 题目思路及分析:

首先最容易想到的暴力解法,先用一个for循环时间复杂度为O(n),取出,一个数x。然后再循环数组里找有没有x+1,x+2,x+3等这些数时间复杂度又为O(n)。最坏的情况下时间复杂度仍然达到了O(n^2)。

原因是我们没办法直接从最小的那个数x去不断加1匹配,就算第一次就直接取出最小的数x去匹配最长序列,也无法保证后面的数不会是最长,所以无论怎样都得循环两次全部都是数组。找出最长的序列。

所以外层循环我们已经从第一个取出了x,x+1,x+2...x+y个数了,内循环又重新像这样取了一次。我们只需要在外层循环的时候找到最小的那个数,计算出它的最长序列就可以了。

因最小开始的那个数x,它的前一位数x-1是不存在的。那么我们将数组中的值去重存入哈希表中。循环哈希表中的值,用循环的值x-1,看哈希表中是否存在该值,如果存在说明当前x不是最小的直接跳过。不存在则用当前值寻找最长序列并记录下来。

代码示例:

class Solution {
    public int longestConsecutive(int[] nums) {
        // 创建Hashset集合,为无序不重复集合
        Set<Integer> numSet = new HashSet();
        // 循环存放数组中的数,主要是用set集合去重
        for (int num : nums) {
            // 如果该num已经存在set则不添加进去
            numSet.add(num);
        }
        // 初始化最长序列次数
        int longestStreak = 0;
        for (int num : numSet) {
            // 判断当前num-1是否在集合中
            if (!numSet.contains(num - 1)) {
                // 记录当前的num值
                int currentNum = num;
                // 当前的序列次数
                int currentStreak = 1;
                // 根据当前的值找到最大的序列次数,
                // 如果当前值currentNum+1在set集合中,增加当前序列次数和当前值
                while (numSet.contains(currentNum + 1)) {
                    // 增加当前值后再次进入while循环判断
                    currentNum += 1;
                    // 增加当前序列次数
                    currentStreak += 1;
                }
                // 每次循环记录的序列次数currentStreak和
                // 最大的序列次数longestStreak比较,最大的重新赋给longestStreak
                longestStreak = Math.max(currentStreak, longestStreak);
            }
        }
        return longestStreak;
    }
}

总结: 把两次循环变成一次循环的关键点在于,在set集合中找到x-1不存在的值。该值可能为作为开始最小的值,那么我们只要找到每个x-1不存在的值比较其最长序列谁最大即可。

 

 

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值