面經總結

Tu9oh0st發表於2019-07-24

演算法

講一下Dijkstra演算法

迪傑斯特拉(Dijkstra)演算法是典型最短路徑演算法,用於計算一個節點到其他節點的最短路徑。
它的主要特點是以起始點為中心向外層層擴充套件(廣度優先搜尋思想),直到擴充套件到終點為止

知道的排序演算法複雜度

排序方法 平均情況 最好情況 最壞情況 輔助空間 穩定性
插入排序 O(n^2) O(n) O(n^2) O(1) 穩定
希爾排序 O(n*log(n))~O(n^2) O(n^1.3) O(n^2) O(1) 不穩定
選擇排序 O(n^2) O(n^2) O(n^2) O(1) 不穩定
氣泡排序 O(n^2) O(n) O(n^2) O(1) 穩定
歸併排序 O(n*log(n)) O(n*log(n)) O(n*log(n)) O(n) 穩定
堆排序 O(n*log(n)) O(n*log(n)) O(n*log(n)) O(1) 不穩定
快速排序 O(n*log(n)) O(n*log(n)) O(n^2) O(1) 不穩定
桶排序 O(N) O(N) O(N) O(1) 不穩定

基本思想

  1. 通過Dijkstra計算圖G中的最短路徑時,需要指定起點s(即從頂點s開始計算)。
  2. 此外,引進兩個集合S和U。S的作用是記錄已求出最短路徑的頂點(以及相應的最短路徑長度),而U則是記錄還未求出最短路徑的頂點(以及該頂點到起點s的距離)。
  3. 初始時,S中只有起點s;U中是除s之外的頂點,並且U中頂點的路徑是”起點s到該頂點的路徑”。然後,從U中找出路徑最短的頂點,並將其加入到S中;接著,更新U中的頂點和頂點對應的路徑。 然後,再從U中找出路徑最短的頂點,並將其加入到S中;接著,更新U中的頂點和頂點對應的路徑。 … 重複該操作,直到遍歷完所有頂點。

操作步驟

  1. 初始時,S只包含起點s;U包含除s外的其他頂點,且U中頂點的距離為”起點s到該頂點的距離”[例如,U中頂點v的距離為(s,v)的長度,然後s和v不相鄰,則v的距離為∞]。
  2. 從U中選出”距離最短的頂點k”,並將頂點k加入到S中;同時,從U中移除頂點k。
  3. 更新U中各個頂點到起點s的距離。之所以更新U中頂點的距離,是由於上一步中確定了k是求出最短路徑的頂點,從而可以利用k來更新其它頂點的距離;例如,(s,v)的距離可能大於(s,k)+(k,v)的距離。
  4. 重複步驟(2)和(3),直到遍歷完所有頂點。

單純的看上面的理論可能比較難以理解,下面通過例項來對該演算法進行說明。

圖解

注意:這裡的B(23)應該是B(13),圖有問題。

EVDCGR.jpg
EVD9i9.jpg

計算64位二進位制整數1的個數

反覆除2取餘數

10萬億個檔案,按照檔名稱排序

外排序

  傳統的排序演算法一般指內排序演算法,針對的是資料可以一次全部載入記憶體中的情況。但是面對海量資料,即資料不可能一次全部載入記憶體,需要用到外排序的方法。外排序採用分塊的方法(分而治之),首先將資料分塊,對塊內資料按選擇一種高效的內排序策略進行排序。然後採用歸併排序的思想對於所有的塊進行排序,得到所有資料的一個有序序列。

  例如,考慮一個1G檔案,可用記憶體100M的排序方法。首先將檔案分成10個100M,並依次載入記憶體中進行排序,最後結果存入硬碟。得到的是10個分別排序的檔案。接著從每個檔案載入9M的資料到輸入快取區,輸出快取區大小為10M。對輸入快取區的資料進行歸併排序,輸出快取區寫滿之後寫在硬碟上,快取區清空繼續寫接下來的資料。對於輸入快取區,當一個塊的9M資料全部使用完,載入該塊接下來的9M資料,一直到所有的9個塊的所有資料都已經被載入到記憶體中被處理過。最後我們得到的是一個1G的排序好的存在硬碟上的檔案。

1TB資料使用32GB記憶體如何排序

  1. 把磁碟上的1TB資料分割為40塊(chunks),每份25GB。(注意,要留一些系統空間!)
  2. 順序將每份25GB資料讀入記憶體,使用quick sort演算法排序。
  3. 把排序好的資料(也是25GB)存放回磁碟。
  4. 迴圈40次,現在,所有的40個塊都已經各自排序了。(剩下的工作就是如何把它們合併排序!)
  5. 從40個塊中分別讀取25G/40=0.625G入記憶體(40 input buffers)。
  6. 執行40路合併,並將合併結果臨時儲存於2GB 基於記憶體的輸出緩衝區中。當緩衝區寫滿2GB時,寫入硬碟上最終檔案,並清空輸出緩衝區;當40個輸入緩衝區中任何一個處理完畢時,寫入該緩衝區所對應的塊中的下一個0.625GB,直到全部處理完成。

繼續優化

磁碟I/O通常是越少越好(最好完全沒有),那麼如何降低磁碟I/O操作呢?

  • 關鍵就在第5和第6步中的40路輸入緩衝區,我們可以先做8路merge sort,把每8個塊合併為1路,然後再做5-to-1的合併操作。
  • 再深入思考一下,如果有多餘的硬體,如何繼續優化呢?有三個方向可以考慮:
  • 使用併發:如多磁碟(併發I/O提高)、多執行緒、使用非同步I/O、使用多臺主機叢集計算。
  • 提升硬體效能:如更大記憶體、更高RPM的磁碟、升級為SSD、Flash、使用更多核的CPU。
  • 提高軟體效能:比如採用radix sort、壓縮檔案(提高I/O效率)等。

手撕K路歸併

#二路歸併排序def MergeSort(list):    if len(list) <= 1:        return list    num = len(list) // 2    left = MergeSort(list[:num])    right = MergeSort(list[num:])    return Merge(left,right)def Merge(left,right):    l,r = 0, 0    result = []    while l < len(left) and r < len(right):        if left[l] < right[r]:            result = left[l]            l += 1        else:            result = right[r]            r += 1    result += left[l:]    result += right[r:]    return result

負載均衡演算法有哪些

負載均衡在大型網站中應用已經是十分普遍了,它在大型網站中處理高併發請求扮演著十分重要的角色。那麼負載均衡演算法又有哪些呢,一下是一些常見的負載均衡演算法:

輪詢法(ROUND ROBIN)

輪詢法基本上算是最簡單的負載均衡演算法了,它的思想就是不管啥情況,對所有的伺服器節點全部按順序來,將請求按照順序輪流地分配到各個伺服器上。這種演算法會使每臺伺服器處理的請求是相同的,所以適合用於伺服器硬體條件基本都相同的場景。

加權輪詢法(WEIGHT ROBIN)

在輪詢演算法的基礎上新增了權重的條件,剛才提到輪詢演算法對所有伺服器“一視同仁”,那麼加權輪詢演算法無疑就是對各個伺服器有了“高低貴賤之分”,沒辦法,伺服器的處理水平不同,只能是讓那些強悍的機器優先並多處理些請求,比較弱的機器嘛就讓它稍稍壓力小一點。

隨機法(RANDOM)

隨機演算法也是一種適用場景比較多的負載均衡演算法,這種演算法基本思想也很簡單,隨機生成一個數字(或者隨機挑一個IP地址)出來,然後挑到誰就去誰家,當然,如果隨機數是等概況生成的,那時間長了,基本上跟輪詢演算法也沒啥區別了,當然區別最主要的還是在順序,隨機麼就沒那麼嚴格的順序了。

加權隨機法(WEIGHT RANDOM)

加權隨機法是在隨機法的基礎上加了加權的條件,隨機法時間長了,基本上跟一般輪詢演算法就沒啥區別了,剛才也提到了,如果伺服器的配置都差不多,那也就算了,但是如果伺服器處理能力差異比較大,那水平高的和水平低的伺服器都給這麼多工,那對於高配置來講就有點浪費,對於低配置的伺服器來講卻有點吃不消,所以在這種配置差異性比較大的情況下,加權的工作還是十分必要的。加權隨機演算法就是適用於這樣的場景。

最小連線法(LEAST CONNECTIONS)

這個演算法思想也很簡單,顧名思義,哪個伺服器的連線少,就分配給哪個伺服器新的請求,合情合理,但是這種演算法的缺點就是,跟我們上面分析的幾種演算法一個意思,一個比較弱的伺服器和一個比較彪悍的伺服器,本來就是前者連線要少,後者要大,如果非得誰的少新請求給誰,那就是弱伺服器的連線要等於強伺服器的連線,無疑這樣會讓弱伺服器吃不消,或者讓強伺服器造成資源浪費,所以在這裡依然可以用加權的方法來解決這個問題——加權最小連線法。

源地址雜湊法(HASH)

Hash法對於大部分碼農來講並不陌生,當年《資料機構》課程上這一節依然能夠栩栩如生地浮現在腦海中。源地址雜湊法就是可以把客戶端的IP地址拿出來,然後計算出IP地址的hash值,hash值是一個很大的正整數,那麼問題來了,怎麼才能對映到相對應的伺服器了,答案很簡單:serverPosition=hashCode%serverListSize。

資料結構

完全二叉樹

完全二叉樹是一種特殊的二叉樹,滿足以下要求:

  1. 所有葉子節點都出現在 k 或者 k-1 層,而且從 1 到 k-1 層必須達到最大節點數;
  2. 第 k 層可以不是滿的,但是第 k 層的所有節點必須集中在最左邊。 需要注意的是不要把完全二叉樹和“滿二叉樹”搞混了,完全二叉樹不要求所有樹都有左右子樹,但它要求:
  3. 任何一個節點不能只有左子樹沒有右子樹
  4. 葉子節點出現在最後一層或者倒數第二層,不能再往上

當我們用陣列實現一個完全二叉樹時,葉子節點可以按從上到下、從左到右的順序依次新增到陣列中,然後知道一個節點的位置,就可以輕鬆地算出它的父節點孩子節點的位置。

二叉查詢樹

二叉查詢樹(BST:Binary Search Tree)是一種特殊的二叉樹,它改善了二叉樹節點查詢的效率。二叉查詢樹有以下性質:

對於任意一個節點 n,

  • 其左子樹(left subtree)下的每個後代節點(descendant node)的值都小於節點 n 的值;
  • 其右子樹(right subtree)下的每個後代節點的值都大於節點 n 的值。

所謂節點 n 的子樹,可以將其看作是以節點 n 為根節點的樹。子樹的所有節點都是節點 n 的後代,而子樹的根則是節點 n 本身。

也就是說,二叉查詢樹中,左子樹都比節點小,右子樹都比節點大,遞迴定義

根據二叉排序樹這個特點我們可以知道:二叉排序樹的中序遍歷一定是從小到大的

平衡二叉樹

平衡二叉樹的提出就是為了保證樹不至於太傾斜,儘量保證兩邊平衡。因此它的定義如下:

  1. 平衡二叉樹要麼是一棵空樹
  2. 要麼保證左右子樹的高度之差不大於 1
  3. 子樹也必須是一顆平衡二叉樹

也就是說,樹的兩個左子樹的高度差別不會太大。

紅黑樹

前面我們已經說過,紅黑樹,本質上來說就是一棵二叉查詢樹,但它在二叉查詢樹的基礎上增加了著色和相關的性質使得紅黑樹相對平衡,從而保證了紅黑樹的查詢、插入、刪除的時間複雜度最壞為O(log n)。

但它是如何保證一棵n個結點的紅黑樹的高度始終保持在h = logn的呢?這就引出了紅黑樹的5條性質:

1)每個結點要麼是紅的,要麼是黑的。  2)根結點是黑的。  3)每個葉結點(葉結點即指樹尾端NIL指標或NULL結點)是黑的。  4)如果一個結點是紅的,那麼它的倆個兒子都是黑的。  5)對於任一結點而言,其到葉結點樹尾端NIL指標的每一條路徑都包含相同數目的黑結點。

正是紅黑樹的這5條性質,使得一棵n個結點是紅黑樹始終保持了logn的高度,從而也就解釋了上面我們所說的“紅黑樹的查詢、插入、刪除的時間複雜度最壞為O(log n)”這一結論的原因。

如下圖所示,即是一顆紅黑樹(下圖引自wikipedia:http://t.cn/hgvH1l):

EVRDVx.png

普通二叉樹刪除過程

刪除節點為葉子節點

EVfv5V.png

刪除節點只有一個子節點:只有一個左子節點和只有一個右子節點

EVfzCT.png

刪除節點有兩個子節點:這種情況比較複雜,需要尋找後繼節點,即比要刪除的節點的關鍵值次高的節點是它的後繼節點。說得簡單一些,後繼節點就是比要刪除的節點的關鍵值要大的節點集合中的最小值。(右子節點的左後代)

如果後繼節點是剛好是要刪除節點的右子節點

EVhp2F.png

如果後繼節點為要刪除節點的右子節點的左後代

EVfjU0.png

雜湊表

雜湊表(Hash table,也叫雜湊表),是根據關鍵碼值(Key value)而直接進行訪問的資料結構。也就是說,它通過把關鍵碼值對映到表中一個位置來訪問記錄,以加快查詢的速度。這個對映函式叫做雜湊函式,存放記錄的陣列叫做雜湊表。

1.開發定址法

  如果遇到衝突的時候怎麼辦呢?就找hash表剩下空餘的空間,找到空餘的空間然後插入。就像你去商店買東西,發現東西賣光了,怎麼辦呢?找下一家有東西賣的商家買唄

2.鏈地址法

  上面所說的開發定址法的原理是遇到衝突的時候查詢順著原來雜湊地址查詢下一個空閒地址然後插入,但是也有一個問題就是如果空間不足,那他無法處理衝突也無法插入資料,因此需要裝填因子(插入資料/空間)<=1。

優先佇列

普通的佇列是一種先進先出的資料結構,元素在佇列尾追加,而從佇列頭刪除。在優先佇列中,元素被賦予優先順序。當訪問元素時,具有最高優先順序的元素最先刪除。優先佇列具有最高階先出 (first in, largest out)的行為特徵。通常採用堆資料結構來實現。

作業系統

併發與並行

併發:交替做不同事情的能力
並行:同時做不同事情的能力
專業術語:
併發:不同的程式碼塊交替執行
並行:不同的程式碼塊同時執行

併發和並行的意義:

併發和並行都可以處理“多工”,二者的主要區別在於是否是“同時進行”多個的任務。

但是 涉及到任務分解(有先後依賴的任務就不能做到並行)、任務執行(可能要考慮互斥、鎖、共享等)、結果合併

程式與執行緒

程式是資源分配的最小單位,執行緒是程式執行的最小單位。
程式有自己的獨立的地址空間, 執行緒共享程式中的資料,使用相同的地址空間。
程式自己通訊方式主要使用特別的方式來進行通訊。執行緒之間的通訊非常的方便, 同一程式下的執行緒共享全域性變數、靜態變數等資料。
多程式程式更加的健壯,其中一個程式死掉了並不影響其他的程式,多執行緒中只要有一個執行緒死掉,那麼整個程式也死掉了。

程式之間進行通訊常用的有幾種方式:管道,訊息佇列, 訊號量, 共享記憶體

執行緒同步通常有4中方式: 臨界區、事件、互斥量、訊號量。

孤兒程式,殭屍程式

孤兒程式:一個父程式退出,而它的一個或多個子程式還在執行,那麼這些子程式將成為孤兒程式。孤兒程式將被 init 程式(程式號為 1)所收養,並由 init 程式對它們完成狀態收集工作。由於孤兒程式會被 init 程式收養,所以孤兒程式不會對系統造成危害。

殭屍程式:一個子程式的程式描述符在子程式退出時不會釋放,只有當父程式通過 wait() 或 waitpid() 獲取了子程式資訊後才會釋放。如果子程式退出,而父程式並沒有呼叫 wait() 或 waitpid(),那麼子程式的程式描述符仍然儲存在系統中,這種程式稱之為殭屍程式。

檔案描述符

核心通過檔案描述符訪問檔案。

一個檔案如何組織存放到硬碟上

不知道

你知道的檔案系統

沒研究過

死鎖

導致死鎖的原因:
1.因為系統資源不足
2.程式執行推進順序不合適
3.資源分配不當
導致死鎖的四個必要條件:
1.一次一個程式只能訪問一個資源, 其他程式不能訪問已分配的資源。
2.當一個程式等待其他程式時, 繼續佔有已分配的資源時
3.不能強行搶佔程式已有的資源
4.存在一個封閉的程式鏈, 導致每一個程式都佔有下一個程式所需的資源

銀行家演算法

EV40SO.png

計算機網路

OSI七層模型

EV4hp8.jpg

五層模型

EV4Wff.jpg

TCP/IP協議棧

不知道,有很多,UDP、TCP、HTTP、HTTPS、DNS、DHCP

time-wait的作用

  • 確保最後一個確認報文能夠到達。如果 B 沒收到 A 傳送來的確認報文,那麼就會重新傳送連線釋放請求報文,A 等待一段時間就是為了處理這種情況的發生。
  • 等待一段時間是為了讓本連線持續時間內所產生的所有報文都從網路中消失,使得下一個新的連線不會出現舊的連線請求報文。

    HTTP

客戶端傳送的 請求報文 第一行為請求行,包含了方法欄位。

GET

獲取資源

當前網路請求中,絕大部分使用的是 GET 方法。

HEAD

獲取報文首部

和 GET 方法類似,但是不返回報文實體主體部分。

主要用於確認 URL 的有效性以及資源更新的日期時間等。

POST

傳輸實體主體

POST 主要用來傳輸資料,而 GET 主要用來獲取資源。

更多 POST 與 GET 的比較請見第九章。

PUT

上傳檔案

由於自身不帶驗證機制,任何人都可以上傳檔案,因此存在安全性問題,一般不使用該方法。

PATCH對資源進行部分修改

PUT 也可以用於修改資源,但是隻能完全替代原始資源,PATCH 允許部分修改。

DELETE

刪除檔案

與 PUT 功能相反,並且同樣不帶驗證機制。

OPTIONS

查詢支援的方法

查詢指定的 URL 能夠支援的方法。

會返回 Allow: GET, POST, HEAD, OPTIONS 這樣的內容。

CONNECT

要求在與代理伺服器通訊時建立隧道

使用 SSL(Secure Sockets Layer,安全套接層)和 TLS(Transport Layer Security,傳輸層安全)協議把通訊內容

加密後經網路隧道傳輸。

TRACE

追蹤路徑

伺服器會將通訊路徑返回給客戶端。

傳送請求時,在 Max-Forwards 首部欄位中填入數值,每經過一個伺服器就會減 1,當數值為 0 時就停止傳輸。通常不會使用 TRACE,並且它容易受到 XST 攻擊(Cross-Site Tracing,跨站追蹤)。

狀態碼

狀態碼 類別 含義

1XX Informational(資訊性狀態碼) 接收的請求正在處理

2XX Success(成功狀態碼) 請求正常處理完畢

3XX Redirection(重定向狀態碼) 需要進行附加操作以完成請求

4XX Client Error(客戶端錯誤狀態碼) 伺服器無法處理請求

5XX Server Error(伺服器錯誤狀態碼) 伺服器處理請求出錯

三次握手

第一次握手:主機A傳送位碼為syn=1,隨機產生seq number=x的資料包到伺服器,客戶端進入SYN_SEND狀態,等待伺服器的確認;主機B由SYN=1知道,A要求建立聯機;

第二次握手:主機B收到請求後要確認聯機資訊,向A傳送ack number(主機A的seq+1),syn=1,ack=1,隨機產生seq=y的包,此時伺服器進入SYN_RECV狀態;

第三次握手:主機A收到後檢查ack number是否正確,即第一次傳送的seq number+1,以及位碼ack是否為1,若正確,主機A會再傳送ack number(主機B的seq+1),ack=1,主機B收到後確認seq值與ack=1則連線建立成功。客戶端和伺服器端都進入ESTABLISHED

態,完成TCP三次握手。

TCP位碼,有6種標示:SYN(synchronous建立聯機) ACK(acknowledgement 確認) PSH(push傳送) FIN(finish結束) RST(reset重置) URG(urgent緊急)

Sequence number(順序號碼) Acknowledge number(確認號碼)

EV4H7n.png

四次揮手

EV4qkq.png

POST傳檔案,怎麼知道是不是傳輸完了

不知道

TCP,UDP區別

tcp是傳輸控制協議,其提供面向連線、可靠的位元組流服務,通訊雙方必須依照三次握手協議連線之後才能傳輸資料, tcp提供了超時重傳、 丟棄重複資料、檢驗資料流量控制等功能。
UDP是使用者資料包協議, 它提供了一個簡單的不可靠的面向無連線的服務,在雙方未連線時也能傳輸資料因而速度特別快。

請求重傳機制

TCP的重傳機制有兩種:超時重傳和快速重傳。

超時重傳

說白了就是在請求包發出去的時候,開啟一個計時器,當計時器達到時間之後,沒有收到ACK,則就進行重發請求的操作,一直重發直到達到重發上限次數或者收到ACK。

快速重傳

當接收方收到的資料包是不正常的序列號,那麼接收方會重複把應該收到的那一條ACK重複傳送,這個時候,如果傳送方收到連續3條的同一個序列號的ACK,那麼就會啟動快速重傳機制,把這個ACK對應的傳送包重新傳送一次。

路由的兩種方式(rip, ospf),怎麼實現

RIP 是一種基於距離向量的路由選擇協議。距離是指跳數,直接相連的路由器跳數為 1。跳數最多為 15,超過 15 表示不可達。RIP 按固定的時間間隔僅和相鄰路由器交換自己的路由表,經過若干次交換之後,所有路由器最終會知道到達本自治系統中任何一個網路的最短距離和下一跳路由器地址。

開放表示 OSPF 不受某一家廠商控制,而是公開發表的;最短路徑優先表示使用了 Dijkstra 提出的最短路徑演算法SPF。

OSPF 具有以下特點:

  • 向本自治系統中的所有路由器傳送資訊,這種方法是洪泛法。
  • 傳送的資訊就是與相鄰路由器的鏈路狀態,鏈路狀態包括與哪些路由器相連以及鏈路的度量,度量用費用、距離、時延、頻寬等來表示。
  • 只有當鏈路狀態發生變化時,路由器才會傳送資訊。

資料庫

redis的持久化

1. 快照: 預設使用這種方式,將資料快照存放在特定的二進位制檔案中。
2. AOF: 將每一條命令都儲存, 恢復時再將每一天命令進行執行。

mysql的B+樹

事務

資料庫事務的4個特性:原子性、永續性、一致性、隔離性

ACID

ACID

1. 原子性(Atomicity)

事務被視為不可分割的最小單元,事務的所有操作要麼全部提交成功,要麼全部失敗回滾。

回滾可以用回滾日誌來實現,回滾日誌記錄著事務所執行的修改操作,在回滾時反向執行這些修改操作即可。

2. 一致性(Consistency)

資料庫在事務執行前後都保持一致性狀態。在一致性狀態下,所有事務對一個資料的讀取結果都是相同的。3. 隔離性(Isolation)

一個事務所做的修改在最終提交以前,對其它事務是不可見的。

4. 永續性(Durability)

一旦事務提交,則其所做的修改將會永遠儲存到資料庫中。即使系統發生崩潰,事務執行的結果也不能丟失。

使用重做日誌來保證永續性。

分散式瞭解什麼

更多的機子,處理更多的資料。

資料庫如何建索引

資料庫索引對於非主鍵索引使用B樹, 對於主鍵索引使用B+樹

對於建立索引的列, mysql的查詢效率會提高很多。

設計模式

檔案併發訪問量很高的時候,怎麼保證可用性

限流

設計一個負載均衡演算法,實現每個使用者隨機訪問不同伺服器,不能重複

源地址hash,因為hash值小概率出現重複

設計一個系統,限制單個使用者每5分鐘只能訪問100次介面

令牌桶演算法,知道有這麼一回事,但是沒有仔細研究過

說一下怎麼實現nginx的反向代理功能

不太瞭解,反向代理伺服器架設在伺服器端,通過緩衝經常被請求的頁面來緩解伺服器的工作量,將客戶機請求轉發給內部網路上的目標伺服器;並將從伺服器上得到的結果返回給Internet上請求連線的客戶端,此時代理伺服器與目標主機一起對外表現為一個伺服器。

專案

專案中為什麼用訊息佇列,哪些場景用到了訊息佇列

解耦、非同步、削峰。

相關文章