更新時間:2025-03-29 11:57:02作者:佚名
前言
在談論這個問題之前,我想談談一個問題:“技術采訪中正在測試什么?”
到底要進行技術采訪
今天,當每個人都知道如何做問題時,面試官還知道每個人都可以做問題并為面試做準備,每個人都可以編寫代碼。那么,為什么您仍在面試中研究這些問題呢?那么,為什么有些人在編寫代碼后仍然掛斷電話呢?
眾所周知,美國主要制造商的訪談中有80%正在采用算法,實際上,在過去的5 - 10年中,該算法僅在Google和Yahoo領導。盡管國內制造商對算法研究并不那么熱情,但他們越來越關注。
那么,算法采訪真的只是參加算法測試嗎?顯然不是。從本質上講,什么測試是思考問題的方式,分析和解決問題的能力以及與同事溝通的能力,以查看您是否可以積極進步來解決問題。
回答想法
例程是:
盡管這是例行程序,但這不是一種有效的工作方式嗎?
當您收到問題時,您應該首先要澄清。因為工作就是這種情況。與提問網站的網站不同,面試官通常不會一次給您所有條件,而是要求您考慮并詢問他。然后,通過此鏈接,面試官將知道您如何看待問題,您是否正在全面考慮,與他人進行交流以及與您合作的未來是什么。
就像我們工作時一樣,我們需要不斷澄清產品經理,尤其是未定義的零件。反復的討論是,銳化刀不會延遲木材的砍伐。然后,這個過程可能需要1-2周的時間,而您將不愿意開始,否則,如果您努力工作,您將朝著錯誤的方向發展,這將是一個完全的離開。面試期間也是如此。撰寫代碼后,面試官說這不是我想問的。當時沒有時間,是我們為此付出了代價。
第二個分析思想是當務之急,也是本文的核心。我將以LRU緩存為例,以展示我的思維方式和分析。
第三點是編寫代碼沒有什么可說的,最終需要實現。
第四點是運行測試,許多學生可能會忘記它,因此,如果您可以主動提出運行測試用例,那么用一些示例進行測試非常好。
有人說我做了每個問題,為什么我仍然失敗?然后比較這四個點以查看哪個鏈接是錯誤的。
持續測試的原因
此外,為什么主要公司喜歡接受這個問題?
首先,它可用于在多個方面和維度上檢查候選人:此問題測試基本技能,測試數據結構的理解和使用,并測試您是否可以編寫可讀代碼。在45-60分鐘的采訪中找出真正的候選人水平并不容易。
其次,由于這個問題很困難或容易,因此它可以像leetcode的問題一樣簡單,并且很難將系統設計的內容包含在Redis中的近似LRU算法。
因此,跟進可以無限地深入。如果面試官想問您可以回答自己想要的一切,那么強大的雇用自然將無法逃脫。一些學生只會進入第一或第二級。訪談是選擇最好的過程。其他學生將比您了解更多,并且他們具有良好的溝通能力。自然,其他人會得到報價。
讓我們以這個問題為例。讓我們在這里簡要介紹我的思維過程,并給您一些建議。歡迎在消息區域分享您的想法。
什么是lru cachelru
LRU =最近使用的
這是一種緩存驅逐策略[1]
LRU算法假定將來將不會使用最少使用的信息,因此,當容量受到限制時,這些不經常使用的信息可以被踢出并釋放。
例如,當有熱門新聞時,每個人都在搜索此信息。剛剛被一個人搜索的信息的可能性也高于兩天前搜索的過時新聞的可能性。因此,我們啟動了很長一段時間沒有使用的信息,也就是說貝語網校,最近使用的信息被趕出了。
例如:我們的內存能力為5,現在我們有五個1-5的數字。
我們現在想添加一個新號碼:6
但是容量已經滿,因此需要踢出一個。
然后,根據規則,您將擁有此緩存彈出策略。例如:
LRU的規則是踢出很長一段時間沒有使用的內容,其隱含的假設是,它認為最近使用該信息的概率將來會更大。
在我們的示例中,我們踢出了最古老的1,然后變成:
連續迭代...
什么是緩存?
一個簡單的理解是:保存一些可重復使用的信息,以便以后可以快速獲取信息。
至于它的存在,這是不確定的。最常見的是,它存在于內存中,即內存緩存,但也可以在內存中存在。
還有更多用法場景,例如支持緩存的春季@CACH。上個月,我在工作中使用了此注釋。當然,它是由我們公司打包的,這大大減少了對某個服務器的電話數量并解決了性能問題。
例如,在進行數據庫查詢時,如果您不想每次要求時調用數據庫,則我們將一些常用的數據存儲在內存中以提高訪問性能。
這個設計思想實際上遵循著名的“ 28法”。在閱讀和編寫數據庫時,每個I/O過程都會大量消耗很多,但實際上80%的請求使用了20%的數據,因此將這20%的數據放入內存可以大大提高整體效率。
簡而言之,緩存的目的是存儲一些可重復使用的信息,以便可以快速獲得未來的請求。
LRU緩存
然后我們知道LRU和CACHE,我們將在一起是LRU CACH:
緩存滿足后,使用LRU算法清理老人。
詳細的思想解釋
說了很多話,讓我們來解決問題的肉!
每個人都知道,這個經典的問題是使用hashmap + double鏈接列表,或使用Java中現成的linkedhashmap,但是為什么呢?您如何看待使用這兩個數據結構?如果您在面試中沒有清楚地解釋這一點,并且不要清楚地解釋思維過程,那么正確編寫代碼是沒有用的。
與工作中的設計思想類似,沒有人會告訴我們要使用哪些數據結構。一般的想法是首先考慮哪些操作,然后基于這些操作,然后查看哪些數據結構是合適的。
分析操作
讓我們分析此LRU緩存需要哪些操作:
首先,最基本的操作是能夠從中讀取信息,否則我該如何快速獲取信息?
然后,您必須添加新信息,并且新信息最近使用。
在添加新信息之前,您必須檢查是否存在任何空間。如果沒有空間,則必須先將舊的空間踢出,并且您需要能夠找到舊的舊空間并刪除它。
如果添加的新信息已經在緩存中,則意味著密鑰已經存在。為了更新值,您只需要調整此信息的優先級,該信息已從上次使用到最新信息。
查找數據結構
第一個操作很明顯。我們需要一個可以快速搜索的數據結構。它是哈希圖。如果您不了解hashmap的原理和設計規則,則可以在官方帳戶中發送消息“ hashmap”并給您熱門文章;
但是隨后的操作hashmap不再有用。 。 。
來吧,讓我們計算基本數據結構:
陣列,LinkedList,堆棧,隊列,樹,BST,Heap,Hashmap
在執行此類數據結構問題時,您將列出所有數據結構并一一分析它們。有時這不是因為這種數據結構不好,而是因為其他數據結構更好。
如何稱呼更好?忘記了我們的測量標準!時間和空間復雜性,快速審查遞歸文章,并在官方帳戶中回復“遞歸”以獲取它。
然后我們的分析如下:
數組,堆棧和隊列基本上是由數組實現的(當然,堆棧和隊列也可以使用linkedlist實現。)。插入新的,刪除舊的,然后調整訂單。數組可以完成或o(n),并且不能使用。
同樣,時間復雜度為O(logn)。
即使可能的話remove是什么意思?怎么讀,堆都是O(logn)。
linkedlist,有點好。按照從舊到新的順序,可以安排,刪除,插入和移動,并且它們都可以是O(1)!但是,刪除時,我還需要一個以前的指針來刪除它,因此我需要一個double linkedlist。
然后,我們的數據結構最終確定為:
hashmap + double linkedlist
清楚地定義數據結構的內容
選擇數據結構后,您需要清楚地定義每個數據結構的存儲內容以及這兩個數據結構如何相關。這是核心問題。
讓我們首先考慮一個場景。在搜索引擎中,如果您輸入問題問題,Google將返回答案。
然后,讓我們假設存儲了這兩個數據結構,然后查看這些操作。如果它們倆都很平滑remove是什么意思?怎么讀,那就沒有問題。如果有任何問題,我們將對其進行調整。
現在,我們的hashmap和linkedlist看起來像這樣:
然后讓我們回顧一下這四個操作:
操作1,沒問題,只需閱讀hashmap的答案,o(1);
操作2。添加一組新的問答,并且必須添加兩個數據結構。首先,我們需要確定當前緩存中是否存在此Q。然后,我們使用hashmap來判斷。
但是,您如何找到linkedlist的節點?這不是我們要尋找一個接一個的遍歷的東西,因為它需要o(n)時間,我們要使用o(1)時間進行操作。
這意味著以這種方式無法錄制。您還需要在linkedlist中記錄每個listNode的位置。這是這個問題的關鍵。
自然要記錄listNode的位置信息,即Hashmap,也就是說,保存每個listNode的參考。
考慮一下,這實際上是正確的。無需在hashmap中記錄答案。答案只需要在linkedlist中記錄。
之后,當我們更新和移動每個節點時,無需更改其引用,因此不需要更改hashmap,而移動的唯一一件事是先前的下一個指針。
然后再考慮一下,實際上無需在linkedlist中記錄問題,無論如何,在哈希姆普中就有它。
這兩個數據結構用于彼此協調,無需記錄相同的信息。
更新的數據結構如下:
通過這種方式,我們分析使用了哪些數據結構,每個數據結構中存儲的內容以及物理含義是什么。
實際上,Java中的LinkedHashmap實施得很好。但是,即使您可以在面試中使用它,它也會逐步派生,而不是一旦看到問題就知道如何使用它,而是乍一看只是記住答案。
同學問我,面試官是否問我是否以前做過這個問題,我應該如何回答?
答:說實話。
誠意在訪談和工作中非常重要,所以說實話。但是,如果面試官不問,則無需這么說。 。 。
實際上,面試官不在乎。您之前已經做過這個問題,因為每個人都做過,基本上已經做到了。提出這個問題是毫無意義的。只要您可以清楚地分析問題并清楚地解釋邏輯,如果您做到了怎么辦?許多做過問題的人無法清楚地解釋它。 。 。
總結
讓我們總結這四個操作:
第一個操作是get()API,無話可說。
兩個,三個,四個是put()API,這有點麻煩:
繪畫時,您在談話時說話和寫作,每個步驟均為從高級到詳細信息再到代碼,將代碼模塊化。
當我畫這張照片時,面試官沒有要求我編寫代碼,然后直接進入了下一個問題...
然后,如果面試官要求您寫作,那就寫。 。 。
class?LRUCache?{
??//?HashMap:?
??//?LinkedList:?
??public?static?class?Node?{
??????int?key;
??????int?val;
??????Node?next;
??????Node?prev;
??????public?Node(int?key,?int?val)?{
??????????this.key?=?key;
??????????this.val?=?val;
??????}
??}
??Map?map?=?new?HashMap<>();
??private?Node?head;
??private?Node?tail;
??private?int?cap;
??public?LRUCache(int?capacity)?{
??????cap?=?capacity;
??}
??public?int?get(int?key)?{
??????Node?node?=?map.get(key);
??????if(node?==?null)?{
??????????return?-1;
??????}?else?{
??????????int?res?=?node.val;
??????????remove(node);
??????????appendHead(node);
??????????return?res;
??????}
??}
??public?void?put(int?key,?int?value)?{
??????//?先?check?有沒有這個?key
??????Node?node?=?map.get(key);
??????if(node?!=?null)?{
??????????node.val?=?value;
??????????//?把這個node放在最前面去
??????????remove(node);
??????????appendHead(node);
??????}?else?{
??????????node?=?new?Node(key,?value);
??????????if(map.size()???????????????appendHead(node);
??????????????map.put(key,?node);
??????????}?else?{
??????????????//?踢走老的
??????????????map.remove(tail.key);
??????????????remove(tail);
??????????????appendHead(node);
??????????????map.put(key,?node);
??????????}
??????}
??}
??private?void?appendHead(Node?node)?{
??????if(head?==?null)?{
??????????head?=?tail?=?node;
??????}?else?{
??????????node.next?=?head;
??????????head.prev?=?node;
??????????head?=?node;
??????}
??}
??private?void?remove(Node?node)?{
??????//?這里我寫的可能不是最?elegant?的,但是是很?readable?的
??????if(head?==?tail)?{
??????????head?=?tail?=?null;
??????}?else?{
??????????if(head?==?node)?{
??????????????head?=?head.next;
??????????????node.next?=?null;
??????????}?else?if?(tail?==?node)?{
??????????????tail?=?tail.prev;
??????????????tail.next?=?null;
??????????????node.prev?=?null;
??????????}?else?{
??????????????node.prev.next?=?node.next;
??????????????node.next.prev?=?node.prev;
??????????????node.prev?=?null;
??????????????node.next?=?null;
??????????}
??????}
??}
}
/**
*?Your?LRUCache?object?will?be?instantiated?and?called?as?such:
*?LRUCache?obj?=?new?LRUCache(capacity);
*?int?param_1?=?obj.get(key);
*?obj.put(key,value);
*/
總結
然后,讓我們回去面試,為什么許多訪談都集中在算法考試上?這樣的采訪的原因是什么?算法問題面試能否真正衡量一個人的工作能力? (當然,對于某些工作經驗,人們還將檢查系統設計的內容。)
這是我一直在考慮的一個問題,下班后,我越來越認為這種采訪確實有效。
因為我們需要的是解決未知問題的能力,因此可能會忘記知識,但是思考問題的方式總是跟隨我們,我們需要不斷改進。然后,在堅實的基本技能的前提下,有正確的方法和想法可以指導您,沒有什么是不可能的。
參考
[1]
緩存替代政策:
重磅!程序員大白交流群-學術微信交流群已成立
額外贈送福利資源!邱錫鵬深度學習與神經網絡,pytorch官方中文教程,利用Python進行數據分析,機器學習學習筆記,pandas官方文檔中文版,effective java(中文版)等20項福利資源
獲取方式:掃描下方二維碼入群交流
點開群公告即可領取下載鏈接
注意:請大家添加時修改備注為 [學校/公司 + 姓名 + 方向]
例如 —— 哈工大+張三+對話系統。
號主,微商請自覺繞道。謝謝!
推薦閱讀
關于程序員大白
程序員大白是一群哈工大,東北大學,西湖大學和上海交通大學的碩士博士運營維護的號,大家樂于分享高質量文章,喜歡總結知識,歡迎關注[程序員大白],大家一起學習進步!