1. 程式人生 > >面試常見演算法總結

面試常見演算法總結

這裡是我在網上搜索的一些面試常見演算法,總結一下,利人利己。

top k 問題:

選取第k大(前k大)的數可以採用類似於快速排序的方法, 利用快速排序的思想,從陣列S中隨機找出一個元素X,把陣列分為兩部分Sa和Sb。Sa中的元素大於等於X,Sb中元素小於X。這時有兩種情況:
1. Sa中元素的個數小於k,則Sb中的第k-|Sa|個元素即為第k大數;
2. Sa中元素的個數大於等於k,則返回Sa中的第k大數。時間複雜度近似為O(n)

也可以用最大堆的方法,pop k次即可。

海量資料的top k 問題:

比如在一億(N)個數中選取最大的10000(m)個,這時候要分情況討論,如果說記憶體不足的話,那麼可以採用建立一個m最小堆,然後遍歷N個數,如果大於堆頂則插入。

如果記憶體足夠的情況,可以直接採用快速排序方法,可以藉助分治法,比如把N個數分為100份數,分別找出100個最大的10000,然後最後在100萬中找10000個最大的。

選取頻率最高問題

海量資料的top k 問題,如果有1g大小的檔案,需要統計其中出現頻率最高的100個詞,有一個1G大小的一個檔案,裡面每一行是一個詞,詞的大小不超過16位元組,記憶體限制大小是1M。返回頻數最高的100個詞。

方案:順序讀檔案中,對於每個詞x,取hash(x)%5000,然後按照該值存到5000個小檔案(記為x0,x1,…x4999)中。這樣每個檔案大概是200k左右。

如果其中的有的檔案超過了1M大小,還可以按照類似的方法繼續往下分,直到分解得到的小檔案的大小都不超過1M。
對每個小檔案,統計每個檔案中出現的詞以及相應的頻率(可以採用trie樹/hash_map等),並取出出現頻率最大的100個詞(可以用含100個結點的最小堆),並把100個詞及相應的頻率存入檔案,這樣又得到了5000個檔案。下一步就是把這5000個檔案進行歸併(類似與歸併排序)的過程了。

通常就是先hash對映到不同的小檔案中,然後通過hash map求頻率,最後歸併

有一個數組,設其為N1,如何取出前N2大個數,數字都是0-10000之間的 。 可以用基數排序,時間複雜度為o(n)

1.陣列中逆序對計算。(劍指offer)
2.判讀一個樹是不是另一個樹的子樹(劍指offer)
3.資料流要求o(1)求得中位數,o(lgn)插入(劍指offer)
4.順時針列印矩陣(劍指offer)
5.複雜連結串列複製(劍指offer)
6.二叉排序樹中第k小的數(劍指offer)
7.反轉連結串列遞迴 、非遞迴(劍指offer)
8.連結串列中倒數第k個結點(劍指offer)
9.陣列中超過一半的數字(劍指offer)
10.左旋轉字串(劍指offer)
11.把二叉樹列印成多行(劍指offer)
12.旋轉陣列查詢(劍指offer)
13.連結串列歸併排序
14.Trapping Rain Water

https://leetcode.com/problems/trapping-rain-water/
15.Longest Palindromic Substring https://leetcode.com/problems/longest-palindromic-substring/
16.Gray Code https://leetcode.com/problems/gray-code/
17.Binary Tree Maximum Path Sum https://leetcode.com/problems/binary-tree-maximum-path-sum/
18.Search for a Range https://leetcode.com/problems/search-for-a-range/
19.算術表示式轉逆波蘭表示式(字尾表達)
20.k-means
21.字串由大小寫字母組成,要求去重,只允許使用幾個int臨時變數,要求時間複雜度儘可能少
22.青蛙每次跳臺階,每次一步或者二步,青蛙總共可以跳n次,臺階共m階(n<=m),每個臺階有若干害蟲,使得青蛙吃的害蟲最多。
23.左右括號組成的字串,去除最少使得剩餘的字串是合法的(符合左右括號規則)
24.實現5選3 組合
25.陣列中後面的數減前面的數差的最大值,要求時間、空間複雜度儘可能低
26.多個有序陣列的歸併
27.多個有序陣列求交集
28.二個有序陣列求差集
29.字串中最長不重複子串
30.小於10萬的迴文數的個數

給定兩個正整數x,y,x有兩中狀態轉移方式:一個是f(x) = 2*x + 1,另一個是g(x) = 3*x+1,問x最少能夠幾次轉移到y,轉移不到輸出-1。

int func(int x, int y){
if(x < 0) return -1;
if(x > y) return -1;
if(x == y) return 0;
int l = func(2*x+1,y);
int r = func(3*x+1,y);
if(l == -1 && r == -1) return -1;
if(l == -1) return r + 1;
return l + 1;
}