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
提示:
0 <= nums.length <= 105
-109 <= nums[i] <= 109
解题分析及思路:
方法:并查集
思路:
并查集的主要解题思路是将两个不连通的分量连起来,最终得到若干个连通分量。
针对本题,遍历数组nums
,将数组中的每个数字num
和num+1
作为并查集的分量,有条件的连接起来,最终获取到最长连续序列的长度。
例如,针对数组[100,4,200,1,3,2]
,通过并查集连通分量的方法,最终会得到[100]
、[200]
和[1,2,3,4]
三个连通分量,那么最长连续序列的长度为4。
由于数据量过大,不适合使用数组来存储并查集的分量,而是使用哈希表来存储并查集的分量。
func longestConsecutive(nums []int) int {
var numSet = make(map[int]int)
for _, num := range nums {
numSet[num] = num
}
var find func(num int) (int, bool)
find = func(num int) (int, bool) {
if v, ok := numSet[num]; ok {
if v != num {
if v1, ok1 := find(v); ok1 {
numSet[num] = v1
}
}
return numSet[num], true
}
return 0, false
}
var union func(num1, num2 int)
union = func(num1, num2 int) {
v1, ok1 := find(num1)
v2, ok2 := find(num2)
if ok1 && ok2 {
if v1 != v2 {
numSet[v1] = v2
}
}
}
for _, num := range nums {
union(num, num+1)
}
var maxLen = 0
for _, num := range nums {
if v, ok := find(num); ok {
if v-num+1 > maxLen {
maxLen = v - num + 1
}
}
}
return maxLen
}
复杂度:
- 时间复杂度:O(n)
- 空间复杂度:O(n)
执行结果:
- 执行耗时:142 ms,击败了22.20% 的Go用户
- 内存消耗:13.7 MB,击败了5.02% 的Go用户