搬磚 面試常考的常用資料結構與演算法

2021-09-12 11:24:29 字數 3582 閱讀 7726

資料結構與演算法,這個部分的內容其實是十分的龐大,要想都覆蓋到不太容易。在校學習階段我們可能需要對每種結構,每種演算法都學習,但是找工作筆試或者面試的時候,要在很短的時間內考察乙個人這方面的能力,把每種結構和演算法都問一遍不太現實。所以,實際的情況是,企業一般考察一些看起來很基本的概念和演算法,或者是一些變形,然後讓你去實現。也許看起來簡單,但是如果真讓你在紙上或者是計算機上快速地完成乙個演算法,並且設計測試案例,最後跑起來,你就會發現會很難了。這就要求我們要熟悉,並牢固掌握常用的演算法,特別是那些看起來貌似簡單的演算法,正是這些用起來很普遍的演算法,才要求我們能很紮實的掌握,在實際工作中提高工作效率。遇到複雜的演算法,通過分析和紮實的基本功,應該可以很快地進行開發。

閒話少說,下面進入正題。

一.資料結構部分

1.陣列和鍊錶的區別。(很簡單,但是很常考,記得要回答全面)

c++語言中可以用陣列處理一組資料型別相同的資料,但不允許動態定義陣列的大小,即在使用陣列之前必須確定陣列的大小。而在實際應用中,使用者使用陣列之前有時無法準確確定陣列的大小,只能將陣列定義成足夠大小,這樣陣列中有些空間可能不被使用,從而造成記憶體空間的浪費。鍊錶是一種常見的資料組織形式,它採用動態分配記憶體的形式實現。需要時可以用new分配記憶體空間,不需要時用delete將已分配的空間釋放,不會造成記憶體空間的浪費。

從邏輯結構來看:陣列必須事先定義固定的長度(元素個數),不能適應資料動態地增減的情況,即陣列的大小一旦定義就不能改變。當資料增加時,可能超出原先定義的元素個數;當資料減少時,造成記憶體浪費;鍊錶動態地進行儲存分配,可以適應資料動態地增減的情況,且可以方便地插入、刪除資料項。(陣列中插入、刪除資料項時,需要移動其它資料項)。  

從記憶體儲存來看:(靜態)陣列從棧中分配空間(用new建立的在堆中), 對於程式設計師方便快速,但是自由度小;鍊錶從堆中分配空間, 自由度大但是申請管理比較麻煩.

從訪問方式來看:陣列在記憶體中是連續儲存的,因此,可以利用下標索引進行隨機訪問;鍊錶是鏈式儲存結構,在訪問元素的時候只能通過線性的方式由前到後順序訪問,所以訪問效率比陣列要低。

2.鍊錶的一些操作,如鍊表的反轉,鍊錶存在環路的判斷(快慢指標),雙向鍊錶,迴圈鍊錶相關操作。

3.佇列(特殊的如優先順序佇列),棧的應用。(比如佇列用在訊息佇列,棧用在遞迴呼叫中)

4.二叉樹的基本操作

二叉樹的三種遍歷方式(前序,中序,後序)及其遞迴和非遞迴實現,三種遍歷方式的主要應用(如字尾表示式等)。相關操作的時間複雜度。

5.字串相關

整數,浮點數和字串之間的轉換(atoi,atof,itoa)

字串拷貝注意異常檢查,比如空指標,字串重疊,自賦值,字串結束符'/0'等。

二.演算法部分

1.排序演算法:

排序可以算是最基本的,最常用的演算法,也是筆試面試中最常被考察到的演算法。最基本的氣泡排序,選擇排序,插入排序要可以很快的用**實現,這些主要考察你的實際編碼能力。堆排序,歸併排序,快排序,這些演算法需要熟悉主要的思想,和需要注意的細節地方。需要熟悉常用排序演算法的時間和空間複雜度。

各種排序演算法的使用範圍總結:(1)當資料規模較小的時候,可以用簡單的排序演算法如直接插入排序或直接選擇排序。(2)當檔案的初態已經基本有序時,可以用直接插入排序或氣泡排序。(3)當資料規模比較大時,應用速度快的排序演算法。可以考慮用快速排序。當記錄隨機分布的時候,快排的平均時間最短,但可能出現最壞的情況,這時候的時間複雜度是o(n^2),且遞迴深度為n,所需的棧空間問o(n)。(4)堆排序不會出現快排那樣的最壞情況,且堆排序所需的輔助空間比快排要少。但這兩種演算法都不是穩定的,若要求排序時穩定的,可以考慮用歸併排序。(5)歸併排序可以用於內排序,也可以用於外排序。在外排序時,通常採用多路歸併,並且通過解決長順串的合併,產生長的初始串,提高主機與外設並行能力等措施,以減少訪問外存額次數,提高外排序的效率。

2,查詢演算法

能夠熟練寫出或者是上機編碼出二分查詢的程式。

3.hash演算法

4.一些演算法設計思想。

貪心演算法,分治演算法,動態規劃演算法,隨機化演算法,回溯演算法等。這些可以根據具體的例子程式來複習。

5.stl

stl(standard template library)是乙個c++領域中,用模版技術實現的資料結構和演算法庫,已經包含在了c++標準庫中。其中的vecor,list,stack,queue等結構不僅擁有更強大的功能,還有了更高的安全性。除了資料結構外,stl還包含泛化了的迭代器,和執行在迭代器上的各種實用演算法。這些對於對效能要求不是太高,但又不希望自己從底層實現演算法的應用還是很具有**力的。

經過一段時間的資料結構與演算法的學習,和學習了前人的經驗,為了更好的指導自己(希望也能幫助到別人)之後資料結構與演算法的學習,總結一下資料結構與演算法學習的方法。

一、記住資料結構,記住演算法思想(是什麼)

我覺得這個是資料結構與演算法學習最基礎的部分。

學完之後,你至少得能給人說明白,什麼是」堆疊「,什麼是」平衡二叉樹「等等等吧。我之所以說」記住「,是希望這些能夠形成長久記憶,儲存到你的」硬碟「裡,而不僅僅在學習的時候過了一遍你的」記憶體「。還有乙個問題,什麼才叫」記住資料結構「。我覺得,第一步,資料結構最直觀的東西你得記住吧(如標題背景圖,來自資料結構和演算法動態視覺化 (chinese))。這種直觀的記憶可能在不知不覺中就完成了,但為了更好的記住,還需去刻意記憶和偶爾的複習。第二步,你得記憶該資料結構的定義與性質與特點等等等吧。例如,學習哈夫曼樹的時候。哈夫曼樹的定義:wpl(帶權路徑長度)最小的二叉樹;哈夫曼樹的特點:(1)沒有度為1的結點(2)n個葉子結點的哈夫曼樹共有2n-1個結點(3)哈夫曼樹的任意非葉節點的左右子樹交換後仍是哈夫曼樹。關於」資料結構「,需要記憶的內容也需要自己在其中慢慢領悟。

至於」記住演算法思想「,舉個例子,思考我們如何構造乙個」哈夫曼樹「。當然,在知道它的定義後,我們可以自己去設計乙個演算法。如果,自己可以想出來,恭喜你。如果自己沒想到,再看到先人的解決辦法後,不是僅僅「驚嘆」一聲,更要去記住它。

我強調「記住」,並沒有死記硬背的意思,而是,很多東西的理解和創新都是以記憶為前提的。

二、進行大量相關程式設計練習,用程式語言去實現某一資料結構上的演算法(怎麼辦)

就我而言,這個過程是最難的。很多時候,理解乙個演算法很容易,很容易在紙上去模擬乙個演算法的實現過程。但,具體實現,則是另一回事。一定得先自己思考,然後再去看書中給的程式語言實現。在我看來,這一過程已經不屬於「資料結構與演算法」的內容了。而是你綜合素質的體現,如何真正理解問題和用程式設計技巧實現,很考驗自己。這一過程,很難靠記憶。而在不斷敲**的過程中去體會一些直覺上的東西。如何用遞迴解決問題,如何使用迴圈,如何使用"哨兵」等等等等。當然,敲完後需要去思考總結,看看能不能總結出一些」小套路「並記住。

三、」記住「特定情景下,利用某一特定的資料結構,去解決問題 (為什麼+怎麼辦)

每介紹一種資料結構,浙大資料結構與演算法的mooc課程都會有乙個實際問題來作為「引子」,回答了「這種資料結構為什麼會出現」。有的是為了實現特定的操作,有的是為了時間和空間上(大部分考慮的是時間複雜性)效率的更高(所以,沒事的時候,分析一下演算法的時間複雜性)。這些東西,我們也須理解記憶。每一資料結構都有其特性,去解決某一類問題,我們需要去記憶,去感悟。

最後,在學習過程中,如何形成乙個屬於自己的知識體系(準備在「印象筆記」中單開乙個「資料結構與演算法」的筆記本);如何去「記住」(記好筆記,多多複習);在學習過程中,遇到挫折,產生挫敗感該如何處理(這個是必然會發生的,總有難以理解不會的地方);如何進行心態方面的調整(欲速則不達,不過也有」敏捷學習「的概念)。在之後資料結構與演算法的學習中,將繼續完善這一篇文章。。。

面試常考的常用資料結構與演算法

資料結構與演算法,這個部分的內容其實是十分的龐大,要想都覆蓋到不太容易。在校學習階段我們可能需要對每種結構,每種演算法都學習,但是找工作筆試或者面試的時候,要在很短的時間內考察乙個人這方面的能力,把每種結構和演算法都問一遍不太現實。所以,實際的情況是,企業一般考察一些看起來很基本的概念和演算法,或者...

面試常考的常用資料結構與演算法

資料結構與演算法,這個部分的內容其實是十分的龐大,要想都覆蓋到不太容易。在校學習階段我們可能需要對每種結構,每種演算法都學習,但是找工作筆試或者面試的時候,要在很短的時間內考察乙個人這方面的能力,把每種結構和演算法都問一遍不太現實。所以,實際的情況是,企業一般考察一些看起來很基本的概念和演算法,或者...

面試常考資料結構與演算法

資料結構部分 1 陣列和鍊錶的區別。很簡單,但是很常考,記得要回答全面 c 語言中可以用陣列處理一組資料型別相同的資料,但不允許動態定義陣列的大小,即在使用陣列之前必須確定陣列的大小。而在實際應用中,使用者使用陣列之前無法確定陣列的大小,只能夠將陣列定義成足夠大小,這樣陣列的空間可能不被使用,從而造...