題目描述
給定一個未排序的整數數組,找出最長連續序列的長度。
要求算法的時間復雜度為。
示例:
輸入: [100, 4, 200, 1, 3, 2]
輸出: 4
解釋: 最長連續序列是 [1, 2, 3, 4]。它的長度為 4。
題目解析
乍一看,我們能馬上想到的方法,就是先進行一次排序,再查找,可是就算我們常用的快速排序也有的復雜度,不合題意,所以這道題我們不能直接用排序。
這時,我們可以犧牲一些空間,來降低時間復雜度。
解法:哈希表
將無序變為有序,并不一定需要直接排序,我們可以用哈希表來“曲線救國”。雖然題目給出的序列是無序的,但是哈希表可以非常高效地訪問無序序列。
我們可以建立一個無序哈希表unordered_map<int, bool> visited
,哈希表的鍵對應數組的索引,其值表示數組中的元素是否被訪問過。
對于每個元素,我們可以以該元素為中心,分別向左、向右查找連續元素,直到不連續為止,記錄這個序列的長度,直到找出最大長度。
遍歷每個元素,再以每個元素為中心再次進行迭代,似乎,這是一個的算法呀?
別擔心!在遍歷每個中心元素時,我們會把標記為true
的元素跳過,因為,在這個題目的條件下,一個元素只能屬于一個連續序列 ,所以我們無需再關心被訪問過的中心元素,它一定會被某一個連續序列所包含。我們的算法,仍然屬于級別。
代碼:
class Solution {
public:
int longestConsecutive(vector<int>& nums) {
unordered_map<int, bool> visited;
for(auto i : nums)
visited[i] = false;
int maxLen = 0;
for(auto i : nums){
if(visited[i])continue;//如果這個元素被訪問過,那么他一定就不再屬于另外一個連續序列,直接跳過
int len = 1;//當前序列的長度
visited[i] = true;
for(int j = i + 1; visited.find(j) != visited.end(); ++j){
visited[j] = true;
len++;
}
for(int j = i - 1; visited.find(j) != visited.end(); --j){
visited[j] = true;
len++;
}
maxLen = max(maxLen, len);
}
return maxLen;
}
};
復雜度分析
時間復雜度:,請仔細思考上面的解題思路
空間復雜度:,因為引入了一個哈希表