算法面試指南

做者:Educative

翻譯:瘋狂的技術宅前端

https://www.educative.io/blog...ios

未經容許嚴禁轉載c++

image.png

算法是技術面試的重要組成部分,尤爲是在國內外的大廠中。本文將爲你介紹在面試中須要瞭解的常見算法以及提升它們效率的方法(這是面試中常見的問題),最後會爲你提供一些練習題。程序員

基本概述

你須要審視的基本概念是:面試

  • 條件語句:if-else 語句,switch 語句和條件表達式
  • 循環:for 循環,while 循環,do-while 循環
  • 函數:迭代函數和遞歸函數
  • 數組

一旦掌握了基礎知識,就能夠開始進入在面試以前應該瞭解的中間概念;具體來講,本文將向你展現一些關鍵的算法範例(以及使它們高效的方法),這些範例對於學習解決面試中的編碼問題相當重要。算法

漸進分析-提升程序效率

在咱們深刻研究算法範式以前,應該對計算機程序相對於算法的時間複雜性和效率說些什麼——一種被稱爲「漸近分析」的概念。在面試中,可能不會要求你直接計算算法的複雜度,但可能會要求你計算所編寫的算法的複雜度或讓你改善一個算法的複雜度。segmentfault

複雜度是算法效率的近似度量,而且與你編寫的每一個算法都相有關。這是全部程序員都必須意識到的事情。有兩種複雜度:時間和空間。時間複雜度和空間複雜度實質上是算法處理某些輸入時將分別花費多少時間和多少空間的近似值。一般要解決如下三個問題:數組

  • 最佳狀況——表示爲 Big Omega 或 Ω(n)
  • 平均狀況——表示爲 Big Theta 或Θ(n)
  • 最壞的狀況——表示爲 Big O 表示法或 O(n)

Big O 是分析算法的首選方法,由於在大多數狀況下,平均狀況和最佳案例沒法洞察算法的效率。服務器

找到算法的 Big O 複雜度

若是你在面試中被要求找到算法的 Big O 複雜性,這是通常的經驗法則:微信

  • 刪除前導常數項
  • 忽略低階項

例:找到時間複雜度爲 3n³ + 4n + 2的算法的 Big O 複雜度,將其簡化爲O(n³)。

漸近分析——怎樣在不給你方程的狀況下計算時間複雜度

計算算法的時間複雜度時,你須要採起三個步驟:

  • 列出代碼中的全部基本操做
  • 計算每次執行的次數
  • 將全部計數加起來獲得一個方程

這是一個簡單的例子,用於測量大小爲 n 的 for 循環的時間複雜度。這是一個大小爲 n 的循環:

#include <iostream>
using namespace std;
int main(){
  int n = 10;  //  0(1)
  int sum = 0; // 0(1)
  for (int i=0; i<n; i++)
    sum+=2; // 0(1)
  cout << sum; // 0(1)
  return 0;
}

首先,將代碼分紅多個單獨的操做,而後計算執行該代碼的次數,以下所示:

image.png

在對每一個操做執行了多少次進行計數以後,只需將全部這些計數相加便可得出該程序的時間複雜度。

$$ \begin{align} 時間複雜度 & = 1 + 1 + 1 +(n + 1)+ n + n + 1 \\ & = 3 +(n + 1)+ 2n + 1 \\ & => 3n + 5 \end{align} $$

漸進分析的通常技巧:

  • 列表或數組每次通過 $c \times 長度$ 的次數進行迭代時,最有可能的時間複雜度是 O(n) 。
  • 當你看到一個問題,每次問題空間中的元素數量減半時,它的時間複雜度極可能是 O(logn)。
  • 只要有一個單獨的嵌套循環,問題的複雜度就極可能是二次方。

用於計算算法時間複雜度的有用公式:

image.png

什麼是算法範式?

算法範式是「構建有效解決問題的通用方法」;換句話說,它們是解決問題的方法、策略或技術,對於每一個程序員都是必不可少的。花時間學習這些,由於你頗有可能會在面試中用到其中一種或多種算法。

算法範式之因此出色,是由於它們奠基了適合解決各類不一樣問題的框架,包括:

  • 分治——一種將問題分解爲較小子問題的模式,而後將其遞歸求解並組合起來(對於樹排序來講很是有用)。
  • 回溯 ——一種解決問題的算法技術,它嘗試一次逐步構建一個解決方案,並刪除那些不能知足問題約束的解決方案。
  • 動態規劃——遞歸函數的優化算法。使用動態規劃,你能夠保存子問題的結果,這樣咱們就能夠沒必要在稍後須要時從新計算它們。

面試時應注意哪些算法?

  • 暴力法——這種方法要求咱們經過嘗試全部可能的方法,來找到問題的解決方案。這一般是最早想到的算法,儘管它可能效率最低,但至少能夠保證你可以找到一種解決方案。
  • 貪心算法——一種算法範式,它逐步構建一個解決方案,這意味着它將會選擇下一個可以提供最明顯且最直接的好處的解決方案。
  • 動態規劃(如上所述)
  • 分而治之(如上所述)
  • 排序和搜索算法——歸併排序、快速排序、選擇排序、冒泡排序、插入排序
  • 圖算法——廣度優先圖遍歷,深度優先圖遍歷

如何進行技術面試

  • 確保你已掌握基礎知識。
  • 瞭解如何使用漸近分析優化程序。
  • 請注意你可使用的不一樣算法及其對複雜度的影響。

一組幫你爲面試作好準備的練習題

漸近分析:計算下面給出的代碼段的 Big O 複雜度。

int main(){
   int n = 10;
   int sum = 0;
   float pie = 3.14;
   
   for (int i=1; i<n; i+=3){
     cout << pie << endl;
     for (int j=1; j<n; J+=2){
       sum += 1;
       cout << sum << endl;
     }
   }
}

排序和搜索算法:實現一個函數,該函數接受兩個可變長度的排序數組,並找到兩個數組的中位數。

圖算法:實現一個函數,該函數返回給定級別的無向圖的節點數。

貪心算法:假設存在無限數量的 25 美分,10 美分,5 美分和 1 美分硬幣,實現一個函數來計算表明 V 美分的硬幣數量。

動態規劃算法:一個孩子正在上 n 級樓梯,每次能夠走 1 步,2 步或 3 步。實現一個函數,計算孩子上樓梯的可能方式。

分治法:給定 2 個有 k 行和 44 個排序列的二維數組,以及一個大小爲 $k \times n$ 的空一維輸出數組,用分治法將全部元素從 k 個排序數組複製到 $k \times n$ 個輸出數組。

總結

若是你要進行技術面試,必須爲展現本身對各類算法的瞭解作好準備,並瞭解每種算法的複雜度。熟悉上面提到的算法範例(即分治、暴力、貪婪),諺語云:「實踐出真知」,因此你須要花時間去練習實現不一樣的算法,並計算其複雜度,由於開發人員在編碼時必須意識到這一點。

你能夠採起一些步驟來確保下次面試成功:

熟悉各類算法:不要只記住解決方案。花時間瞭解構成每種算法的模式以及應該採起的方法。

作功課:練習的次數越多,感受就會越溫馨。

下一步…學習,準備和練習:只是憑藉看老的面試題和博客文章來準備面試是不夠的,你須要真正的實踐經驗。


本文首發微信公衆號:前端先鋒

歡迎掃描二維碼關注公衆號,天天都給你推送新鮮的前端技術文章

歡迎掃描二維碼關注公衆號,天天都給你推送新鮮的前端技術文章

歡迎繼續閱讀本專欄其它高贊文章:


相關文章
相關標籤/搜索