【做題心得】最長連續序列
阿新 • • 發佈:2021-10-22
一道水題,我首先想到的做法是暴力的列舉。
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