128 Longest Consecutive Sequence
We will talk about three approaches:
- brute force solution \(O(n^2)\) in time, \(O(n)\) in space
- only look for head of the sequence \(O(n)\) in time, \(O(n)\) in space
- union find, 也能做到\(O(n)\) in time, 但需要a lot more code. 以后再来看看吧.
Approach 1: Brute Force Solution
This is the first solution came to my mind when i saw it. The outer loop is executed at most n times while the inner loop is executed at most n times. So, the time complexity is O(n^2). The space complexity is O(n) because we are using a set to store the numbers.
Since we have to traverse the nums, the only thing left for optimize is the inner while loop.
If you have a sequence like
nums = [100, 4, 200, 1, 3, 2]
[1, 2, 3 ,4], we will check 4 times, which is unnecessary. We only need to check the first number of the sequence, and how do we do that? Please see approach 2.
class Solution:
def longestConsecutive(self, nums: List[int]) -> int:
# 1st pass: get them into the set()
# 2nd pass: iterate over nums and create a while loop to check the hashmap
# O(n) in time, O(n) in space
count = set(nums)
best_length = 0
for num in count:
curr = num
curr_length = 0
while curr in count:
curr_length += 1
curr += 1
best_length = max(best_length,curr_length)
return best_length
Approach 2: O(n) in time and space
我们知道我们的目标是找到每一个sequence的头部,那么头部有什么区别呢? 头部的前一个数字不在set里面, 所以我们可以用这个特性来优化我们的算法。
# counting sequence from head
class Solution:
def longestConsecutive(self, nums: List[int]) -> int:
# 1st pass: get them into the set()
# 2nd pass: iterate over nums and create a while loop to check the hashmap
# O(n) in time, O(n) in space
count = set(nums)
best_length = 0
for num in count:
if num -1 not in count:
curr = num
curr_length = 0
while curr in count:
curr_length += 1
curr += 1
best_length = max(best_length,curr_length)
return best_length
Note
同理,for sequence, 决定尾部可以用尾部的下一个数字不在set里面来判断。但人们更倾向于从头部开始计算,因为left -> right is common in a lot of cultures.