非算法方向的你前端
面了多少次試?git
最後,由於不懂算法,程序員
死在了半路上?github
這些痛,面試
做爲技術創新型公司的小編——個推君算法
怎麼會不懂?編程
爲此,個推君特請了我司經驗豐富的面試官json
爲你奉上一份熱乎的面試寶典。後端
寶典可不是面試題哦設計模式
僅送給想認真鑽研的童鞋
幫你們梳理知識點
讓你們觸類旁通,
offer拿到手軟!
注:此處建議你們使用 C 語言來學習數據結構與算法。
首先咱們得從數據結構開始,你們至少得數據結構有個概念,大部分的算法題均須要帶入數據結構的概念來處理。
科班出身的程序員或多或少學習過數據結構,推薦你們重溫下這本書,溫故而知新。
在說算法以前和你們科普兩個重要的理論知識:算法的時間複雜度與空間複雜度。
算法的時間複雜度,用來度量算法的運行時間,記做: T(n) = O(f(n))。它表示隨着 輸入大小n 的增大,算法執行須要的時間的增加速度能夠用 f(n) 來描述,而且會忽略常量部分,。
舉個例子
int aFunc(void) { printf("Hello, World!\n"); // 須要執行 1 次 return 0; // 須要執行 1 次 }
調用此方法,printf("Hello, World!n"); 執行了一次,那麼咱們記作 T(n) = O(1)
int aFunc(int n) { for(int i = 0; i<n; i++) { // 須要執行 (n + 1) 次 printf("Hello, World!\n"); // 須要執行 n 次 } return 0; // 須要執行 1 次 }
此處輸出語句被執行了 n 次,那麼咱們記作 T(n) = O(n)
再看一個
int aFunc(int n) { for(int i = 0; i<3*n; i++) { for(int j = 0; j<2*n; i++) { // 須要執行 (n) 次 printf("Hello, World!\n"); // 須要執行 n 次 } return 0; }
此處輸出語句被執行了 (3n)(2*n) 次,f(n)=6n^2,因爲咱們是忽略常量的,因此 T(n)=O(n^2)
是對一個算法在運行過程當中臨時佔用存儲空間大小的量度,記作S(n)=O(f(n))。
int i = 1; int j = 2; ++i; j++; int m = i + j
代碼中的 i、j、m 所分配的空間都不隨着處理數據量變化,所以它的空間複雜度 S(n) = O(1)。
int[] m = new int[n] for(i=1; i<=n; ++i) { j = i; j++; }
這段代碼中,第一行new了一個數組出來,這個數據佔用的大小爲n,這段代碼的2-6行,雖然有循環,但沒有再分配新的空間,所以,這段代碼的空間複雜度主要看第一行便可,即 S(n) = O(n)
字符串或串(String)是由數字、字母、下劃線組成的一串字符。通常記爲 s=「a1a2···an」(n>=0)。它是編程語言中表示文本的數據類型。在程序設計中,字符串(string)爲符號或數值的一個連續序列,如符號串(一串字符)或二進制數字串(一串二進制數字)。
這個很少說了,敲代碼的都懂,一切皆可字符串。
所謂數組,是有序的元素序列。若將有限個類型相同的變量的集合命名,那麼這個名稱爲數組名。組成數組的各個變量稱爲數組的份量,也稱爲數組的元素,有時也稱爲下標變量。用於區分數組的各個元素的數字編號稱爲下標。
在 C 語言中,數組可分爲一維數組,二維數組,多維數組等。而涉及到怎麼建立數組這邊就細講了,各個語言的的申明方法以及使用方法都不太相同。
鏈表是一種物理存儲單元上非連續、非順序的存儲結構,數據元素的邏輯順序是經過鏈表中的指針連接次序實現的。鏈表由一系列結點(鏈表中每個元素稱爲結點)組成,結點能夠在運行時動態生成。每一個結點包括兩個部分:一個是存儲數據元素的數據域,另外一個是存儲下一個結點地址的指針域。
鏈表是咱們比較經常使用的數據結構,若是在編程的過程當中,須要進行頻繁 增&刪 操做的,優先使用鏈式存儲結構。
鏈表分爲咱們常見的單鏈表,還有雙鏈表以及循環鏈表
typedef struct LNode { int data; //data中存放結點數據域(默認是int型) struct LNode *next; //指向後繼結點的指針 }LNode;
棧做爲一種數據結構,是一種只能在一端進行插入和刪除操做的特殊線性表。它按照先進後出的原則存儲數據,先進入的數據被壓入棧底,最後的數據在棧頂,須要讀數據的時候從棧頂開始彈出數據(最後一個數據被第一個讀出來)。棧具備記憶做用,對棧的插入與刪除操做中,不須要改變棧底指針。
棧是一種先進後出的的數據結構,有入棧和入棧兩種常見操做。
typedef struct Stack{ // 棧 PNODE pTop; PNODE pBottom; }STACK,*PSTACK;
隊列是一種特殊的線性表,特殊之處在於它只容許在表的前端(front)進行刪除操做,而在表的後端(rear)進行插入操做,和棧同樣,隊列是一種操做受限制的線性表。進行插入操做的端稱爲隊尾,進行刪除操做的端稱爲隊頭。隊列中沒有元素時,稱爲空隊列。
隊列是一種先進先出的的數據結構,有入隊和出隊兩種常見操做,通常有順序隊列,雙向隊列,循環隊列。
typedef struct{ ELemType data[MaxSize]; int front, rear; }SqQueue;
它是由n(n>=1)個有限結點組成一個具備層次關係的集合。把它叫作「樹」是由於它看起來像一棵倒掛的樹,也就是說它是根朝上,而葉朝下的。
樹是一個大類,樹下面又分 二叉樹,平衡二叉樹,AVL 樹,字典樹,哈夫曼樹,紅黑樹,b 樹等,考察的最多的是二叉樹與紅黑樹
下圖是二叉樹的結構體定義
typedef struct TNode{ TElemType data; struct TNode *lchild,*rchild; }TNode,*Tree;
圖是由頂點的有窮非空集合和頂點之間邊的集合組成, 一般表示爲: G(V,E), 其中,G表示一個圖,V是圖G中頂點的集合,E是圖G中邊的集合。
一個圖就是一些頂點的集合,這些頂點經過一系列邊結對(鏈接)。頂點用圓圈表示,邊就是這些圓圈之間的連線。頂點之間經過邊鏈接。頂點有時也稱爲節點或者交點,邊有時也稱爲連接。
粗略的講了下數據結構的理論,終於要進入正餐了。算法題大體分爲如下幾大類,還有一些小類就不舉例了,好比位運算,回溯算法等。
查找也能夠叫作搜索,這是算法分類裏面最最最普通的一個模塊,查找分爲 線性查找,數表查找,哈希查找
掌握程度: 查找 類型的較多問題,每一種數據結構都有本身的查找類型的經典算法,好比 數組對應的最小值/最大值查找、字符串對應的關鍵字查找、鏈表對應的迴環判斷等、樹對應的深度/廣度優先,二叉樹對應的 前/中/後 遍歷,最 小/大 堆查找 ,這些本質是都是和查找算法相關的。
推薦範例: 這個很差推薦,實在是太多了。
說到排序,你們都很是熟悉了,排序分爲內排序和外排序,由於外排序的出現頻率較低,這邊只進行內排序的分析,咱們常見的選擇,冒泡,快排均屬於內排序。
具體的算法不展開了,百度有全家桶
掌握程度:除了基數排序和希爾排序,其餘幾個排序算法均須要能夠默寫算法的程度,接着要進行實戰操做,刷完下面的這些題目,對排序算法會有個清晰的理解。
推薦範例:排序範例
講到遞歸的時候,咱們在使用的過程當中,特別要對遞歸終止的條件有個清晰的把握,否則很容易陷入死循環當中
掌握程度:連接裏面的就 14 到題目,但願所有刷一遍。值得注意的是,遞歸的題目通常來講會有多種解法。
推薦範例:遞歸集合
動態規劃,又名DP算法(取自其Dynamic Programming的縮寫),最初是運籌學的一個分支,是用來求解決策過程最優化的數學方法。
動態規劃經常適用於有重疊子問題和最優子結構性質的問題,動態規劃方法所耗時間每每遠少於樸素解法。
動態規劃背後的基本思想很是簡單。大體上,若要解一個給定問題,咱們須要解其不一樣部分(即子問題),再根據子問題的解以得出原問題的解。動態規劃每每用於優化遞歸問題,例如斐波那契數列,若是運用遞歸的方式來求解會重複計算不少相同的子問題,利用動態規劃的思想能夠減小計算量。好比咱們常見的爬樓梯的問題,對了這個問題通常有多種解法。
掌握程度: 這類問題的類似度很是的高,但願你們能夠達到舉一反三的境界
推薦範例:買賣股票的最佳時機,爬樓梯
貪心算法(又稱貪婪算法)是指,在對問題求解時,老是作出在當前看來是最好的選擇。也就是說,不從總體最優上加以考慮,他所作出的是在某種意義上的局部最優解。好比咱們常見的爬樓梯問題
掌握程度: 若是不是面試算法工程師的話,建議刷完 10 道簡單的題目便可
推薦範例:貪心算法範例
圖這塊知識會涉及到很深很深的東西,若是不是從事這方向研究的,停留在理論層+一些簡單算法便可,圖裏面有不少的經典算法須要掌握。
好比 普利姆算法,克魯斯卡爾算法等,這些都是很是經典的算法,須要知道經典算法的設計邏輯以及優缺點。
掌握程度: 熟悉各種存儲結構,精通經典算法的實現思路
推薦範例: 圖算法的範例
你們有沒有發現上個章節頻繁的出現了 LeetCode 這個字眼,那麼這個網站究竟是什麼呢?在介紹以前還得和你們說下該怎麼刷題嗎。刷題網站有力扣 (LeetCode 中文版),清華 ACM,浙大 ACM,這幾個網站算法學習生態圈都比較穩定,LeetCode 也是其中的一種,我習慣用力扣(力扣的小編看到的話記得給我加個雞腿),這是一個寶藏網站,裏面的內容很是的多,你們感興趣的能夠深刻研究下。
這上面的題目也就 1117 題而已,能夠從不一樣的維度去刷題,好比難易度,問題分類,經過率等。我推薦是根據
數據結構的分類來,好比你今天學了二叉樹,那麼打開 LeetCode,耗時 2 天刷十道簡單題的二叉樹便可。按照這種思路,差很少 1 個月便可完成上述所描述的題目。但願你們時間還來得及。
這些都是我我的的一些學習經歷,經過這個網站的可視化界面,能夠較直觀對本身的學習有個回顧。
推薦是用 C 語言,由於 C 語言更接近底層,編譯速度會快那麼零點幾毫秒,別小看幾毫秒的時間哦,由於在 LeetCode 上,算法耗時的最小單位是 1 毫秒。。。差一毫秒但是差異巨大的。
若是你寫的算法僅打敗了 40%的提交記錄,老學長建議你重寫提交下,算法魅力就在於此,毫秒必爭!一個好的算法可讓程序的編譯速度成幾何倍速的增長。 也能夠直接點擊柱狀圖,會有當前算法耗時的最優算法解。
說了一些 LeetCode 的東西,咱們看看實際開發過程當中,安利你們一個 IDEA 的 LeetCode 的插件,名字就叫 leetcode ,使用這個小插件,能夠幫助咱們快速編譯所寫的 demo。
編寫的算法能夠直接在編譯器裏測試 & 提交。
說個現實的問題,除非是算法工程師,你們在開發的過程當中極少用到算法的,那是否是反向推論算法僅是停留在作題&面試,僅須要應付面試便可了?那是否是隻要瘋狂刷題就能夠了!!!
不過話說回來,不推薦你們這麼玩,推薦你們在理論的基礎上加以實踐,仍是但願你們能夠深刻的學習數據結構與算法,會對計算機的運行有着更深刻的理解,後面是我本身看過的一些書本與優秀公衆號,連接是個人我的刷題庫
https://github.com/LiuLei0571...
《算法 4 》,《漫畫算法》,《大話設計模式》,《大話數據結構》,《劍指 offer》
感謝各位看官閱讀到最後,大家的支持是我創做的源泉,最後給你們放一道我在實際開發中遇到的算法問題。
有如下一個 json 字符串,編寫一個算法測試此 json 是否有迴路。action_chains 裏面有若干個動做,入口動做是 actionid=1,接着去執行下一個動做,下一個動做的 actionid 是上一個動做的 do 參數,出口是 actionid=100。
{ "action_chains": [ { "actionid": "1", "do": "2" }, { "actionid": "2", "do": "3" }, { "actionid": "3", "do": "4" }, { "actionid": "4", "do": "5" }, { "actionid": "5" } ] } 請關注**個推技術學院**公衆號回覆「答案」便可查閱答案。 