【Python刷力扣hot100】128. Longest Consecutive Sequence
问题
给定一个未排序的整数数组nums
,返回最长连续元素序列的长度。
你必须设计一个时间复杂度为O(n)O(n)O(n)的算法。
例1:
Input: nums = [100,4,200,1,3,2]
Output: 4
解析:最长连续元素序列为 [1, 2, 3, 4],因此其长度为 4。
例2:
Input: nums = [0,3,7,2,5,8,4,6,0,1]
Output: 9
例3:
Input: nums = [1,0,1,2]
Output: 3
约束:
0 <= nums.length <= 105
-109 <= nums[i] <= 109
分析
可以先对数组进行排序,之后计算每个顺序序列的长度,但是排序算法时间复杂度为O(nlogn)O(nlogn)O(nlogn)。这种思路不符合题目要求
解:集合(哈希表)
题目要求时间复杂度为O(n)O(n)O(n),一般情况下这个时间复杂度都是遍历有限次数组,得到答案。
如何计算序列长度呢?我们需要找到所有起始位置的数字xxx,看到x+1x+1x+1后就把value值+1,之后不断寻找x+2,x+3,...x+2,x+3,...x+2,x+3,...并用一个变量记录当前最大的value即可。
如何确保找到所有起始位置的数字xxx呢?我们看到xxx后还要看下x−1x-1x−1是否在数组中,若没有x−1x-1x−1,就说明x是起始数字。
有了以上思路,再结合集合的特性,答案就呼之欲出了:
-
第一次遍历:去重,产生一个集合
set
(不含重复元素) -
第二次遍历:遍历集合
set
,看一个数字x时,首先判断x-1
是否在集合中,若在,则说明该数字不是起始数字,跳过,若不在则说明x是起始数字,继续寻找x+1,x+2,...
,同时记录长度,最后输出记录的最大长度即可。
注:查找一个元素是否在集合中的操作,时间复杂度是O(1)O(1)O(1)
集合是只存key、不存value的哈希表
时间复杂度O(n)O(n)O(n):nnn为数组长度,遍历有限次(假设为kkk次)数组,也就是O(kn)O(kn)O(kn),由于k是常数所以最后化简为O(n)O(n)O(n)
空间复杂度O(n)O(n)O(n):哈希表需要存储数组中所有的数,需要O(n)O(n)O(n)空间。
class Solution:def longestConsecutive(self, nums: List[int]) -> int:# 处理空数组情况if not nums:return 0# 将数组转换为集合,便于O(1)时间复杂度的查找num_set = set(nums)max_length = 0# 遍历集合中的每个元素for num in num_set:# 只有当num-1不存在时,才开始计算连续序列if num - 1 not in num_set:current_num = numcurrent_length = 1# 查找连续的下一个元素while current_num + 1 in num_set:current_num += 1current_length += 1# 更新最大长度max_length = max(max_length, current_length)return max_length
力扣的官方题解
class Solution:def longestConsecutive(self, nums: List[int]) -> int:longest_streak = 0num_set = set(nums)for num in num_set:if num - 1 not in num_set:current_num = numcurrent_streak = 1while current_num + 1 in num_set:current_num += 1current_streak += 1longest_streak = max(longest_streak, current_streak)return longest_streak
参考
https://leetcode.cn/problems/longest-consecutive-sequence