1. 程式人生 > >演算法學習筆記(一)

演算法學習筆記(一)

演算法筆記(一)

一 什麼是正確的回答一個演算法問題

 回答一個演算法問題,並不是一下子回答出來一個解決方案,而應該是和麵試官探討的過程,在探討過程中逐漸選擇一個最優方案

對一組資料進行排序

這組資料有什麼樣的特徵?

  • 有沒有包含大量重複的元素? 如果有,三路快排
  • 是否大部分資料距離它的正確位置很近?即是否近乎有序?插入排序最好
  • 取值範圍是否有限?比如對學生成績排序,這樣計數排序更好

有什麼額外要求?

  • 是否要求穩定排序? 如果是,快排不好,歸併排序是更好的選擇

資料的儲存狀態是怎樣的?

  • 快排等演算法依賴陣列的隨機存取的特徵,如果資料儲存在連結串列中,快排不適用,歸併排序更好
  • 資料的大小是否可以裝載在記憶體裡?如果資料很大,或者記憶體很小,不足以裝載到記憶體,需要使用外排序演算法或者對資料進行轉換,比如bitmap演算法
即便一個問題一時回答不上來,也應該積極給出一個方向,讓面試官知道所做出的努力和思考

二、演算法面試優秀不意味著技術面試優秀

專案經歷和專案中遇到的實際問題,考察做專案時是僅僅為了達到要求,還是自己進行了深入的思考

你遇到的印象最深的bug是什麼?

面向物件

設計模式

網路相關;安全相關;記憶體相關;併發相關;

系統設計;scalability(系統在大規模使用時可能遇到的問題)

三、技術面試優秀不等於offer

經常會問其他問題,與人的交流合作、個人思考問題的方式、生活習慣、思維模式、價值觀、對公司的瞭解等等

  • 遇到的最大挑戰是什麼?
  • 你是怎麼解決xxxx的?
  • 遇到xxx你會xxx?
  • 你有什麼要問面試官的?

四、如何準備演算法面試?

演算法導論

完全沒必要那麼大,如果喜歡讀,必須有選擇的讀,跳過理論推導,記住結論即可,後面再回過來慢慢看

五、面試中的時間複雜度

時間複雜度

是一個近似,也跟指令條數有關。假如一個演算法的時間複雜度是O(n),那麼其執行時間是aO(n),前面是一個固定的常數,代表指令條數。

對於時間複雜度的對比,一定要注意是否在相同資料規模下,否則是沒有意義的。

資料規模的概念

如果想要在1s之內解決問題:

  • O(n2)的演算法可以處理大約104級別的資料
  • O(n)的演算法可以處理大約10^8級別的資料
  • O(nlogn)的演算法可以處理大約10^7級別的資料

這個資料是在僅進行簡單的加法操作的情況下得出的,保險起見,可以再除以10

空間複雜度

多開一個輔助陣列: O(n)

多開一個輔助的二維陣列:O(n^2)

多開常數空間:O(1)

注意:遞迴呼叫是有空間代價的,其跟遞迴的深度有關,需要在系統棧中存入狀態

時間複雜度分析

一般的時間複雜度都要從程式碼層面去分析,在有迴圈的程式碼裡,一定要注意迴圈的上下界,舉個例子:

 for (i = 0; i < n; i++) 
    for (j=0; j < 30; j++)
        swap(a, b);

這裡雖然是兩重迴圈,但裡面的迴圈只迴圈了30次,外層迴圈n次,總共30n次,時間複雜度是O(n)

攤還分析

舉個例子,構建一個動態陣列,在陣列元素個數達到陣列容量時進行擴容

void push_back(T value) {
    if (size == capacity)
        resize(2 * capacity)
    data[size++] = value;
}

void resize(int newCapacity) {
    T* newData = new T[newCapacity];
    for (int i =0; i < size; i++)
        newData[i] = data[i];
    delete *data;
}

這裡的程式碼,增加一個元素,時間複雜度是O(1),但裡面增加了一個resize操作,resize的操作時間複雜度是O(n),那麼,push_back的事件複雜度是多少呢?

這裡應該還是O(1),具體分析來說,每增加一個元素時O(1),當增加到滿的時候,此時進行了n次O(1),進行擴容,也是O(n),一共O(2n),一共n次操作,平均下來每次為O(2),還是O(1)

複雜度震盪問題

在動態陣列實現中,有這樣一種實現,增加元素時,每次元素個數達到陣列容量的1/2便進行擴容。同時,在刪除元素時,每次元素個數得到1/2時,進行陣列容量縮減,這樣存在一種極端情況:增加一個元素,進行了擴容,時間複雜度是O(n),擴容之後立馬刪除元素,又要對陣列進行縮減,時間複雜度也是O(n),這樣操作便退化了,造成了複雜度震盪。