1. 程式人生 > 其它 >【做題心得】最長連續序列

【做題心得】最長連續序列

LeetCode 劍指Offer II 119

一道水題,我首先想到的做法是暴力的列舉。

class Solution {
public:

int dp[100100],ans = 1;

int longestConsecutive(vector<int>& nums)
{
    int n = nums.size();

    memset(dp,0,sizeof(dp));
    sort(nums.begin(),nums.end());
    dp[0] = 1;

    if(!n)     return 0;
    if(n == 1) return 1;
    cout
<<n<<endl; for(int i=1;i<n;i++) { if(nums[i] == nums[i-1] + 1) { dp[i] = dp[i-1] + 1; cout<<dp[i]<<" "<<nums[i]<<endl; ans = max(ans,dp[i]); }
else if(nums[i] == nums[i-1]) dp[i] = dp[i-1]; else dp[i] = 1; } return ans; } };

打完瞅了一眼正解,官方給出了Hash表的做法。

class Solution {
public:

int ans = 0;
unordered_set <int > s;

int longestConsecutive(vector<int>& nums)
{
    for(int b:nums)
       s.insert(b);

    
for(int num:s) if(!s.count(num - 1)) { int current_num = num,current_len = 1; while(s.count(current_num + 1)) { current_num++; current_len++; } ans = max(ans,current_len); } return ans; } };

雖然評論區都說一眼就Hash,但是由於本蒟蒻不會用Set,因此沒有想到。如果你想了解Set,請繼續讀下去。

什麼是Set?

set是STL 中一種標準關聯容器。它底層使用平衡的搜尋樹——紅黑樹實現,紅黑樹的效率要高於二叉樹,且插入刪除操作時僅僅需要指標操作節點即可完成,不涉及到記憶體移動和拷貝,刪除的時候類似,稍做變換後把指向刪除節點的指標指向其他節點也OK了。這裡的一切操作就是指標換來換去,和記憶體移動沒有關係,所以效率比較高

set,顧名思義是 “集合” 的意思,在 set 中元素都是唯一的,而且預設情況下會對元素自動進行升序排列,支援集合的交 (set_intersection), 差 (set_difference) 並 (set_union),對稱差 (set_symmetric_difference) 等一些集合上的操作,如果需要集合中的元素允許重複那麼可以使用 multiset。

  1.標頭檔案:<set>
 2.定義:set<int> q;
 3.輸入(插入):insert(x);
 4.刪除指定元素:erase(x);
 5.清空:clear();
 6.判空:empty();
 7.大小:size();
 8.二分查詢:q.lower_bound(x);

有趣的一個性質是,set內部維護一個遞增序列。並且它具有去重功能,在本題中作用巨大。
#include <iostream>
#include <set>

using namespace std;

set <int > s;

int a[10] = {1,2,50,666,7,2,5,-10,-10,0};
 
int main()
{
    for(int i=0;i<10;i++)
           s.insert(a[i]);
    
    for(set<int >::iterator i = s.begin();i != s.end();i++)
       cout<<*i<<" ";

return 0;
}

輸出:-10 0 1 2 5 7 50 666