常見演算法整理(二)

2021-09-06 12:40:35 字數 3546 閱讀 9078

1、從300萬字串中找到最熱門的10條

搜尋的輸入資訊是乙個字串,統計300萬輸入資訊中的最熱門的前10條,我們每次輸入的乙個字串為不超過255byte,記憶體使用只有1g。請描述思想,寫出演算法(c語言),空間和時間複雜度。

255位元組*300萬=7,5500,0000位元組=755,000k=755m=0

.75g

所以完全可以放入記憶體處理,建立乙個字串的hash陣列,然後遍歷所有字串,相應的加一處理,然後排序即可,演算法負責度極為o(n)

2、如何找出字典中的兄弟單詞。給定乙個單詞a,如果通過交換單詞中字母的順序可以得到另外的單詞b,那麼定義b是a的兄弟單詞。現在給定乙個字典,使用者輸入乙個單詞,如何根據字典找出這個單詞有多少個兄弟單詞?

首先定義乙個key,使得兄弟單詞有相同的key,不是兄弟的單詞有不同的key。例如,將單詞按字母從小到大重新排序後作為其key,比如bad的key為abd,good的key為dgoo。

使用鍊錶將所有兄弟單詞串在一起,hash_map的key為單詞的key,value為鍊錶的起始位址。

開始時,先遍歷字典,將每個單詞都按照key加入到對應的鍊錶當中。當需要找兄弟單詞時,只需求取這個單詞的key,然後到hash_map中找到對應的鍊錶即可。

3、找出陣列中出現次數超過一半的數,現在有乙個陣列,已知乙個數出現的次數超過了一半,請用o(n)的複雜度的演算法找出這個數。

答案1:

建立乙個hash_map,key為陣列中的數,value為此數出現的次數。遍歷一遍陣列,用hash_map統計每個數出現的次數,並用兩個值儲存目前出現次數最多的數和對應出現的次數。

這樣可以做到o(n)的時間複雜度和o(n)的空間複雜度,滿足題目的要求。

但是沒有利用「乙個數出現的次數超過了一半」這個特點。也許演算法還有提高的空間。

答案2:

使用兩個變數a和b,其中a儲存某個陣列中的數,b用來計數。開始時將b初始化為0。

遍歷陣列,如果b=0,則令a等於當前數,令b等於1;如果當前數與a相同,則b=b+1;如果當前數與a不同,則令b=b-1

。遍歷結束時,a中的數就是要找的數。

這個演算法的時間複雜度是o(n),空間複雜度為o(

1)。1 2 1 3 1 5 4 1 1 1 1 8 9

b=0 b=0 b=0 b=0 b=0 b=0 b=0 b=0 b=1 b=2 b=3 b=2 b=1

a=1 a=2 a=1 a=3 a=1 a=5 a=4 a=1 a=1 a=1 a=1 a=1 a=1

4、找出被修改的數字

n個空間(其中n<1m),存放a到a+n-1的數,位置隨機且數字不重複,a為正且未知。現在第乙個空間的數被誤設定為-1。已經知道被修改的數不是最小的。請找出被修改的數字是多少。

例如:n=6,a=2,原始的串為5,3,7,6,2,4。現在被別人修改為-1,3,7,6,2,4。現在希望找到5。

回答:

由於修改的數不是最小的,所以遍歷第二個空間到最後乙個空間可以得到a的值。

a到a+n-1這n個數的和是total=na+(n-1)n/2

。  將第二個至最後乙個空間的數累加獲得sub_total。

那麼被修改的數就是total-sub_total。

5、給40億個不重複的unsigned int的整數,沒排過序的,然後再給幾個數,如何快速判斷這幾個數是否在那40億個數當中?

這是我非常喜歡的一道題。

答案:  unsigned int的取值範圍是0到2^32-1。我們可以申請連續的2^32/8=512m的記憶體,用每乙個bit對應乙個unsigned int數字。首先將512m記憶體都初始化為0,然後每處理乙個數字就將其對應的bit設定為1。當需要查詢時,直接找到對應bit,看其值是0還是1即可。

6、在乙個檔案中有10g個整數,亂序排列,要求找出中位數。記憶體限制為2g。

回答:

不妨假設10g個整數是64bit的。

2g記憶體可以存放256m個64bit整數。

我們可以將64bit的整數空間平均分成256m個取值範圍,用2g的記憶體對每個取值範圍內出現整數個數進行統計。這樣遍歷一邊10g整數後,我們便知道中數在那個範圍內出現,以及這個範圍內總共出現了多少個整數。

如果中數所在範圍出現的整數比較少,我們就可以對這個範圍內的整數進行排序,找到中數。如果這個範圍內出現的整數比較多,我們還可以採用同樣的方法將此範圍再次分成多個更小的範圍(256m=2^28,所以最多需要3次就可以將此範圍縮小到1,也就找到了中數)。

7、將多個集合合併成沒有交集的集合。

給定乙個字串的集合,格式如:,,,,要求將其中交集不為空的集合合併,要求合併完成後的集合之間無交集,例如上例應輸出,,。

(1)請描述你解決這個問題的思路;

(2)請給出主要的處理流程,演算法,以及演算法的複雜度

(3)請描述可能的改進。

回答:

集合使用hash_set來表示,這樣合併時間複雜度比較低。

1、給每個集合編號為0,1,2,3

...  

2、建立乙個hash_map,key為字串,value為乙個鍊錶,鍊錶節點為字串所在集合的編號。遍歷所有的集合,將字串和對應的集合編號插入到hash_map中去。

3、建立乙個長度等於集合個數的int陣列,表示集合間的合併關係。例如,下標為5的元素值為3,表示將下標為5的集合合併到下標為3的集合中去。開始時將所有值都初始化為-1

,表示集合間沒有互相合併。在集合合併的過程中,我們將所有的字串都合併到編號較小的集合中去。

遍歷第二步中生成的hash_map,對於每個value中的鍊錶,首先找到最小的集合編號(有些集合已經被合併過,需要順著合併關係陣列找到合併後的集合編號),然後將鍊錶中所有編號的集合都合併到編號最小的集合中(通過更改合併關係陣列)。

4、現在合併關係陣列中值為-1的集合即為最終的集合,它的元素**於所有直接或間接指向它的集合。

演算法的複雜度為o(n),其中n為所有集合中的元素個數。

題目中的例子:  0

:  1:

2:  

3:  4

:  生成的hash_map,和處理完每個值後的合併關係陣列分別為

aaa:

0。[-1,-1,-1,-1,-1

]  bbb:

0,1。[-1,0,-1,-1,-1

]  ccc:

0。[-1,0,-1,-1,-1

]  ddd:

1,4。[-1,0,-1,-1,0

]  eee:

2。[-1,0,-1,-1,0

]  fff:

2。[-1,0,-1,-1,0

]  ggg:

3。[-1,0,-1,-1,0

]  hhh:

4。[-1,0,-1,-1,0

]  所以合併完後有三個集合,第0,

1,4個集合合併到了一起,

常見排序演算法整理

經常忘記簡單的排序演算法,有時間整理下來,便於隨時翻閱,也為了隨用隨取 插入排序演算法 取第乙個數作為有序佇列,從後面的無序佇列中依次取值,在有序佇列中從後向前比較大小,插入到有序佇列中。void insertsort int unsort,int n unsort j temp 選擇排序演算法 與...

javascript 常見演算法整理

字串反轉 因為這個是用的自己的最簡單的方法進行的實現,所以不整理 了 回文 正著讀與反著讀效果一樣,稱為回文 思路 利用陣列的reverse方法,join方法進行拼接,判斷反轉後拼接是否與原資料一致,一致則是回文 出現次數最多的字元 思路 建立乙個物件,然後遍歷字串,字串的每個字元作為物件的key,...

常見加密演算法整理

0x1加密演算法分類 0x11根據加密演算法使用的秘鑰數量,可以將加密體制分為對稱金鑰體制 symmetric cipher,單秘鑰密碼體制,秘密秘鑰密碼體制,對稱秘鑰密碼體制,常規密碼體制 和非對稱秘鑰體制 asymmetric cipher,雙秘鑰密碼體制,公開秘鑰密碼體制,非對稱 密碼體制 對...