最多連續數的子集

2021-06-17 20:17:07 字數 1915 閱讀 5818

給乙個整數陣列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)。並查集可以做到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]。

#include #include #include using namespace std;

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

int find(vector& p, int x)

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

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

vectorhash((max+2), -1); //用於查詢a[i]-1和a[i]+1是否存在

for (int i = 0; i < size; ++i)

hash[ivec[i]] = i;

for (int i = 0; i < size; ++i) }

max = ivec[0];

maxlen = len[0];

for (int i = 1; i < size; ++i) }

}int main()

; vectorivec(a, a + 8);

int max, maxlen;

longest(ivec, max, maxlen);

for (int i = max-maxlen+1; i <= max; ++i)

cout << i << ' ';

cout << endl;

return 0;

}

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

題目 給乙個整數陣列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...

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

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

CCF 出現最多的數

給定n個正整數,找出它們中出現次數最多的數。如果這樣的數有多個,請輸出其中最小的乙個。輸入格式 輸入的第一行只有乙個正整數n 1 n 1000 表示數字的個數。輸入的第二行有n個整數s1,s2,sn 1 si 10000,1 i n 相鄰的數用空格分隔。輸出格式 輸出這n個次數中出現次數最多的數。如...