程式設計師5年的經驗去面試,問了一些數據結構的問題,5分鐘後我淚奔了

職場 發佈 2020-01-26T12:08:12+00:00

對於實習招聘來說,項目經歷可能是獲得面試的敲門磚,但是基礎絕對是贏得面試的通天索。即使是實習招聘,白板寫代碼也很可能逐漸成為主流面試的標配,平時要有意識地鍛鍊這方面能力,要不然面試時沒有IDE真的是做不下去。


對於實習招聘(甚至校招)來說,項目經歷可能是獲得面試的敲門磚,但是基礎絕對是贏得面試的通天索。

即使是實習招聘,白板寫代碼也很可能逐漸成為主流面試的標配,平時要有意識地鍛鍊這方面能力,要不然面試時沒有IDE真的是做不下去。

對自己的真實實力一定要有正確的評估。一個簡單的評估方式是,你的真實能力水平大約只有你所認為的50%甚至更低。

面試是一件很累的事情,要找准自己的位置,避免海投。

作為一名優秀的程式設計師,技術面試都是不可避免的一個環節,一般的技術面試官都會通過自己的方式去考察程式設計師的技術功底與基礎理論知識。

記得面試字節跳動時自己準備了好多的時間,在網上搜索了很多看似會被提問到的題,但是在看見面試官後腦子就一片空白了,因為之前都是學前端的,數據結構和算法一般不太愛怎麼看,工作上也用不著,這次面試的時候經理就著重問了我關於圖像算法.和常用的排序結構老實說這次給我的打擊非常大,因為工作了5年連這樣的題都回答不上來,都還給以前的老師了.

這次我把被問到的題做成一個個小標題,就算是一次總結:


二叉樹(binary tree)和哈希表(hash table)都是很基本的數據結構,但是我們要怎麼從兩者之間進行選擇呢?他們的不同是什麼?優缺點分別是什麼?

散列表的優點很明顯,查詢時間為常數1,最快的查詢速度。二叉樹的查詢速度也很快,為log(n)但是慢於散列表。但是二叉樹相對於散列表的優點是,對於一個二叉查找樹,即binary search tree,其中元素是排序的,而散列表是不排序的。那麼問題就來了,在你手機中,顯然你希望聯繫人是按姓氏排序的,那麼如果你使用散列表,你就需要額外的內存空間進行排序,而二叉查找樹本身就是排好序的,因此節省了寶貴的空間。結論就是,在空間不受限制時,且不需要高頻率的排序操作時,二叉查找樹不如散列表。反之二叉查找樹優於散列表。

二叉搜索樹的效率如何?看起來不如哈希表啊,存在的意義何在?

實際上,我們看一下二叉搜索樹的算法可以得出來一個結果,他的查找效率是O(logn)的,完全不如哈希表查找的效率o(1). 且,二叉搜索樹極端情況下很容易退化成單鍊表,那麼單鍊表的查找效率我們都知道是O(N)的。這個就更慢了。

但,即便如此,二叉搜索樹還有一些哈希表不具備的優點:

  1. 二叉搜索樹用中序遍歷可以很容易對 數據進行排序,這個是哈希表做不到的。
  2. 哈希表遇到哈希衝突的時候需要擴容,這個擴容操作相當耗時,性能有時候不穩定,雖然說二叉搜索樹的性能也不穩定, 但是 我們有更特殊的 平衡二叉搜索樹可以把時間複雜度穩定在O(logn)
  3. 二叉搜索樹比較簡單,數據結構一目了然,遞歸遞歸遞歸就行了,但是哈希表你們懂的,實現起來超級複雜。

所以可以知道,hashmap和二叉搜索樹各有各的優點,具體怎麼用,還是要看實際情況,但是大家要知道這兩種數據結構的 優劣在哪裡以及為什麼?

分析線性表、二叉平衡樹和哈希表存儲數據時各自的優劣

有了散列表為何還要二叉樹?

對於優劣勢,一方面考慮存儲,一方面考慮性能:

  • 線性表:可以用順序表和鍊表實現,而且存儲結構不一樣,性能也不一樣,總的來說線性表的優勢是結構簡單,訪問節點比較快,對單節點的操作比較簡單;適合於小數據量的存儲,並且訪問不存在經常變化的需求;
  • 散列表:實現了隨機訪問,所以性能比較快,但是對於散列函數的設計要求比較高,而且設計需要根據自己的需求進行設計,實現高訪問;
  • 二叉平衡樹:比較靈活,在空間上可以實現高效壓縮存儲,但是對於節點的操作比較複雜

散列表主要可以在O(1)時間內對查找對象定位,但是事實上,如果輸入集合不確定的情況下,可能出現大量的衝突,雖然有很多好的哈希函數,但是隨著隨機輸入,大量衝突還是不可避免,可能出現最差情況。

所以如果輸入結合確定,所需要的就是查詢,則可以考慮使用哈希表,如果輸入集合不確定,則考慮使用平衡二叉樹/紅黑樹,保證達到最大效率

散列表的插入、刪除、查找操作的時間複雜度可以做到常量級的O(1),非常高效。而二叉查找樹在比較平衡的情況下,插入、刪除、查找操作時間複雜度才是O(logn),相對散列表,好像並沒有什麼優勢,那我們為什麼還要用二叉查找樹呢?

我認為有下面幾個原因:

第一,散列表中的數據是無序存儲的,如果要輸出有序的數據,需要先進行排序。而對於二叉查找樹來說,我們只需要中序遍歷,就可以在O(n)的時間複雜度內,輸出有序的數據序列。

第二,散列表擴容耗時很多,而且當遇到散列衝突時,性能不穩定,儘管二叉查找樹的性能不穩定,但是在工程中,我們最常用的平衡二叉查找樹的性能非常穩定,時間複雜度穩定在O(logn)。

第三,籠統地來說,儘管散列表的查找等操作的時間複雜度是常量級的,但因為哈希衝突的存在,這個常量不一定比logn小,所以實際的查找速度可能不一定比O(logn)快。加上哈希函數的耗時,也不一定就比平衡二叉查找樹的效率高。

第四,散列表的構造比二叉查找樹要複雜,需要考慮的東西很多。比如散列函數的設計、衝突解決辦法、擴容、縮容等。平衡二叉查找樹只需要考慮平衡性這一個問題,而且這個問題的解決方案比較成熟、固定。

最後,為了避免過多的散列衝突,散列表裝載因子不能太大,特別是基於開放尋址法解決衝突的散列表,不然會浪費一定的存儲空間。

綜合這幾點,平衡二叉查找樹在某些方面還是優於散列表的,所以,這兩者的存在並不衝突。我們在實際的開發過程中,需要結合具體的需求來選擇使用哪一個。



關鍵字: