渐入佳境,剖析 LeetCode #128 最长连续序列的妙招!
2023-12-09 02:21:41
征服连续序列难题:LeetCode #128 解密
在算法学习的殿堂中,LeetCode 犹如一座屹立的丰碑,考验着算法爱好者的智慧和韧性。其中,#128 最长连续序列问题更是跻身 Top 100 高频题之列,成为算法高手必经的磨砺之路。
问题剖析:连续序列的奥义
给你一个无序整数数组 nums,找出最长的连续正整数序列的长度。例如:
- 对于 nums = [100, 4, 200, 1, 3, 2],最长的连续正整数序列是 [1, 2, 3],因此返回 3。
- 对于 nums = [1, 2, 0, 1],最长的连续正整数序列是 [1, 2],因此返回 2。
解法一:哈希表的巧妙应用
哈希表是一种强大的数据结构,可以快速查找和插入元素。在这个解法中,我们将每个整数 nums[i] 作为键,其对应的连续序列长度作为值。
算法步骤:
- 初始化一个哈希表 map。
- 遍历数组 nums,对于每个元素 nums[i]:
- 如果 map 中包含键 nums[i],则跳过该元素。
- 否则:
- 向前查找比 nums[i] 大的连续整数,计算长度 left。
- 向后查找比 nums[i] 小的连续整数,计算长度 right。
- 将 map[nums[i]] 设置为 left + right + 1。
- 在哈希表中查找具有最大值的键,并返回其对应的值。
解法二:并查集的优雅合并
并查集是一种高效的算法,用于管理不交叠集合的合并和查找操作。在这个解法中,我们将每个整数 nums[i] 视为一个集合的代表元素。
算法步骤:
- 初始化一个并查集 uf。
- 遍历数组 nums,对于每个元素 nums[i]:
- 如果 uf 中不存在包含 nums[i] 的集合:
- 创建一个新的集合,其代表元素为 nums[i]。
- 否则:
- 找到包含 nums[i] 的集合的代表元素 parent。
- 如果 parent + 1 在 uf 中存在,则合并包含 nums[i] 和 parent + 1 的集合。
- 如果 uf 中不存在包含 nums[i] 的集合:
- 返回 uf 中所有集合中元素最多的集合的元素数量。
代码示例:Swift 中的优雅实现
哈希表解法:
func longestConsecutive(_ nums: [Int]) -> Int {
var map = [Int: Int]()
var maxLen = 0
for num in nums {
guard map[num] == nil else {
continue
}
let left = map[num - 1] ?? 0
let right = map[num + 1] ?? 0
let newLen = left + right + 1
maxLen = max(maxLen, newLen)
map[num] = newLen
map[num - left] = newLen
map[num + right] = newLen
}
return maxLen
}
并查集解法:
class UnionFind {
private var parent: [Int]
private var size: [Int]
init(_ n: Int) {
parent = Array(repeating: 0, count: n)
size = Array(repeating: 1, count: n)
for i in 0..<n {
parent[i] = i
}
}
func find(_ x: Int) -> Int {
if parent[x] != x {
parent[x] = find(parent[x])
}
return parent[x]
}
func union(_ x: Int, _ y: Int) {
let rootX = find(x)
let rootY = find(y)
if rootX != rootY {
if size[rootX] > size[rootY] {
parent[rootY] = rootX
size[rootX] += size[rootY]
} else {
parent[rootX] = rootY
size[rootY] += size[rootX]
}
}
}
}
func longestConsecutive(_ nums: [Int]) -> Int {
let uf = UnionFind(nums.count)
var numToIndex = [Int: Int]()
for (i, num) in nums.enumerated() {
numToIndex[num] = i
}
for num in nums {
if let index = numToIndex[num - 1] {
uf.union(i, index)
}
if let index = numToIndex[num + 1] {
uf.union(i, index)
}
}
var maxSize = 0
for i in 0..<nums.count {
maxSize = max(maxSize, uf.size[uf.find(i)])
}
return maxSize
}
结语:探索算法的无穷魅力
LeetCode #128 最长连续序列问题虽看似简单,但其蕴含的算法思想却十分精妙。通过剖析哈希表解法和并查集解法,我们深入理解了如何高效地解决此类问题。在顾毅大师的指导下,我们将算法的魅力娓娓道来,力求让每一位读者都能领悟算法的真谛。
算法的世界,如同一座浩瀚的海洋,蕴藏着无限的知识与挑战。让我们扬帆启航,不断探索算法的奥秘,在算法的征途中书写新的篇章!
常见问题解答:
-
什么是最长连续序列?
最长连续序列是指数组中连续的一组正整数序列,其长度最大。 -
哈希表解法是如何工作的?
哈希表解法将每个整数存储为键,其对应的连续序列长度存储为值。它高效地查找和更新连续序列长度。 -
并查集解法是如何工作的?
并查集解法将每个整数视为一个集合的代表元素,并合并相邻集合。通过查找集合的代表元素,我们可以获得最长连续序列的长度。 -
哪种解法更有效率?
哈希表解法的时间复杂度为 O(n),而并查集解法的平均时间复杂度也为 O(n)。对于大量重复元素的数组,哈希表解法更具优势。 -
LeetCode #128 问题在实际场景中有哪些应用?
该问题在 DNA 测序、数据挖掘和网络分析等领域有广泛应用。