待字閨中之最多連續數的子集

2021-06-22 18:09:08 字數 1752 閱讀 4925

題目**,

給乙個整數陣列a, 找到其中包含最多連續數的子集,比如給:15, 7, 12, 6, 14, 13, 9, 11,則返回: 5:[11, 12, 13, 14, 15] 。

分析:最簡單的方法是sort然後scan一遍,但是要 o(nlgn) , 有什麼 o(n) 的方法嗎?

網上有人用map或set來做,但map或set的複雜度還是o(nlgn)。並查集可以做到o(n),此題用並查集比較簡單。

以下參考

但是該文章給的**有缺陷,就是只能處理正數的情況

並查集是一宗簡單的用途廣泛的演算法和資料結構。並查集是若干個不相交集合,能夠實現較快的合併和判斷元素所在集合的操作。應用很多,比如:求無向圖的連通分量個數,實現kruskal演算法等。

並查集可以方便地進行以下三種操作:

1、make(x):把每乙個元素初始化為乙個集合,初始化後每乙個元素的父節點就是它本身。

2、find(x):查詢乙個元素所在的集合,乙個元素所在的集合用這個集合的祖先節點來標識。判斷兩個元素是否屬於同乙個集合,只要看他們所在集合的祖先節點是否相同即可。

3、union(x, y):合併x、y所在的兩個集合,先利用find()找到兩個集合的祖先,若這兩個祖先節點不是同乙個節點,將其中乙個祖先節點指向另乙個祖先節點即可。(具體哪個祖先指向哪個祖先可以根據實際情況而定)

並查集的優化:在find函式中,每次找祖先節點的複雜度是o(n)。當我們經過遞迴找祖先節點的時候,順便把這條路徑上的所有子孫節點都直接指向祖先,這樣下次find的時候複雜度就變成了o(1)。

回到題目,首先呼叫make(x)將每個元素變成乙個並查集,然後一次掃瞄a[i],檢視a[i]-1是否存在,若存在呼叫union(a[i], a[i]-1);檢視a[i]+1是否存在,若存在呼叫union(a[i]+1, a[i])。在合併的同時更新集合的大小。接下裡的問題是怎麼判斷a[i]-1和a[i]+1是否存在,用雜湊可以解決,而且複雜度是o(1)。

該題中並查集的操作都是基於下標的。我們用p[i]表示a[i]的父節點的下標,用len[i]表示以a[i]為根的集合的大小,我們合併的時候總是將較小值集合的祖先指向較大值集合的祖先,這樣就只需要記錄較大值集合的祖先節點對應的長度。最後掃瞄陣列a和len,找到最大長度maxlen對應的a[i]。最後的結果就是:a[i]-maxlen+1, a[i]-maxlen+2, ..., a[i]。

具體見**,該**使用map做hash表,比原文的vector優越的地方就是可以處理負數

#include #include #include #include using namespace std;

void make(vector& p,vector& len,int x)

int find(vector& p,int x)

//保證x >= y

void union(vector& p,vector& len,int x,int y)

bool exist(map& hash,int value,int x)

return false;

}bool exist(map& hash,int value)

return false;

}void longest(vector& ivec, int& max, int& maxlen)

} max = ivec[0];

maxlen = len[0];

for(i=1;imaxlen)

}}int main()

return 0;

}

如有錯誤,請指正,謝謝

最多連續數的子集

給乙個整數陣列a,找到其中包含最多連續數的子集,比如給 15,7,12,6,14,13,9,11,則返回 5 11,12,13,14,15 最簡單的方法是sort然後scan一遍,但是要o nlgn 有什麼o n 的方法嗎?思路 網上有人用map來做,個人覺得用map的複雜度還是o nlgn 並查集...

劍指offer連續子數的最大和

輸入乙個整型陣列,陣列裡有正數也有負數。陣列中的乙個或連續多個整數組成乙個子陣列。求所有子陣列的和的最大值。要求時間複雜度為 o n 動態規劃思想 轉移方程 dp i 1 0 時,dp i dp i 1 array i dp i 1 0 時,dp i array i dp i 1 小於0,則認為其毫...

最多連續數的子集 並查集 啟發式合併

題目描述 給乙個整數陣列a,找到其中包含最多連續數的子集,比如給 15,7,12,6,14,13,9,11,則返回 5 11,12,13,14,15 思路 初始化每個樹子集乙個集合,預處理每個數的數值雜湊到一張表中,內容存下標,掃一次陣列,每次取找val 1以及val 1的數,如果找到了把兩者的集合...