題目
給定一個未排序的整數數組,找出最長連續序列的長度。
要求算法的時間複雜度爲 O(n)。
示例:
輸入: [100, 4, 200, 1, 3, 2]
輸出: 4
解釋: 最長連續序列是 [1, 2, 3, 4]。它的長度爲 4。
解法1:先排序在比較
這個解法沒啥好說的直接上代碼但是時間複雜度爲O(nlogn)其實不滿足題目要求
class Solution {
public:
int longestConsecutive(vector<int>& nums) {
int size = nums.size();
if(size==0)
return 0;
sort(nums.begin(), nums.end());
int longth = 1; //記錄每個連續子串的長度
int max_longth = 1; //記錄最大子串的長度
for(int i = 0; i < size-1; ++i){
if(nums[i+1] == nums[i])
continue;
if(nums[i+1]-nums[i]==1)
longth++;
else
longth = 1;
max_longth = max(longth, max_longth);
}
return max_longth;
}
};
解法2:備忘錄加遞推
咱們遍歷數組每個元素,並且用一個unordered_map存放元素及其對應下標,再用一個數組記錄每個位置元素對應的連續序列長度,有一個遞推式 length[num] = length[num-1] + 1;意思就是遍歷到某一個元素就再去尋找數組中是否有這個元素減1的數,而我們用length直接就一次遞歸好了把遍歷過的元素的長度存進去了,比如這個示例先遍歷到了4,依次遍歷3,2,1,這幾個元素對應的長度都已經存在length了,下一次遍歷到3直接返回length[2]+1就行,這樣查找複雜度爲O(1);這種解法複雜度爲O(n)
class Solution
{
public:
int longestConsecutive(vector<int>& nums)
{
if(nums.empty())
return 0;
unordered_map<int, int>hash; //給每個數字對應的下標
vector<int>length(nums.size()); //每個下標對應的數字對應的長度
for(int i = 0; i < nums.size(); i++)
{
hash[nums[i]] = i;
}
for(int i = 0; i < nums.size(); i++)
{
if(length[i] > 0) //length[i]不爲0代表對應下標已經計算過長度
continue;
length[i] = caluLength(nums[i], hash, length);
}
int ans = INT_MIN;
for(auto &temp : length)
{
if(temp > ans)
ans = temp;
}
return ans;
}
int caluLength(int num, unordered_map<int, int>&hash, vector<int>&length)
{
if(hash.find(num) == hash.end())
return 0;
int index = hash[num];
if(length[index] > 0) //已經存好了直接返回對應長度
return length[index];
else
{
length[index] = caluLength(num-1, hash, length) + 1; //遞推式
return length[index];
}
}
};