使用者故事 刷演算法面試題的4種思考方式

2021-09-16 18:44:44 字數 4957 閱讀 2638

不管是為了求職面試,還是為了提高自己的演算法基礎能力,「刷演算法題」都是每個程式設計師的必經之路。如何對待刷題?如何讓刷題變得更高效?我們蒐集了來自《演算法面試通關 40 講》的使用者分享,他們也許可以給你一點啟發。

\n\n

剛看老師的課程沒多久, 收穫不多, 我就把自己的第一道練習題解題心得發出來吧。這個是老師講的第一道 leetcode 演算法題: 兩數之和

\n題目:

\n給定乙個整數陣列 nums 和乙個目標值 target,請你在該陣列中找出和為目標值的那 兩個 整數,並返回他們的陣列下標。你可以假設每種輸入只會對應乙個答案。但是,你不能重複利用這個陣列中同樣的元素。

\n示例:

\n給定 nums = [2, 7, 11, 15], target = 9

\n因為 nums[0] + nums[1] = 2 + 7 = 9所以返回 [0, 1]

\n解答如下:

\n完成這道題,第一次花了半個小時,時間還是蠻長的,畢竟是自己完成的第一道 leetcode 演算法題。不過之前確實演算法練習得很少,解法很簡單,用的是窮舉法,連續兩次遍歷,時間複雜度為 o(n²)。

\n

int twosum(int nums, int target) \n    for (int i = 0; i \u0026lt; nums.length; i++) ;\n            }\n        }\n    }\n    return new int[0];\n}\n
\n
int twosum2(int nums, int target) \n\n// 遍歷陣列裡的每乙個元素\n\nfor (int i = 0; i \u0026lt; nums.length; i++) ;\n\n}\n\n}\n\nreturn new int[0];\n\n}\n
\n

將傳入的陣列轉換成 hashmap, 利用 hashmap 查詢速度快的優勢 o(1),將整體查詢時間降到 o(n),hashmap 通過以空間換取速度的方式,將查詢速度提高到了 o(n),這裡用到了分別兩次的迴圈,雖然時間複雜度變成了 o(n),但實際上是兩倍的 o(n)。

\n之後又思考了一下,發現一次迴圈也能解決問題,時間複雜度可以再次減半,變成真正的 o(n),於是便有了下面的**。

\n

int twosum3(int nums, int target) ;\n            }\n            map.put(nums[i], i);\n        }\n        return new int[0];\n    }\n
\n

之後我寫了乙個簡單的測試案例來測試這 3 種演算法的耗時,建立了乙個長度為 10 萬的陣列,分別執行這 3 種演算法,發現當資料量大的時候,第 2 種和第 3 種演算法比第 1 種快了不是乙個數量級。而且資料量越大,速度差異越明顯:

\n

int nums = new int[100 * 1000];\n\n        for (int i = 0; i \u0026lt; nums.length; i++) \n\n        long start = system.currenttimemillis();\n        //int indexresult = twosum(nums, 9); // 陣列長度 100000 耗時 1578 ms\n        //int indexresult = twosum2(nums, 9); // 陣列長度 100000 耗時 20 ms\n        int indexresult = twosum3(nums, 9);// 陣列長度 100000 耗時 14 ms\n\n        long end = system.currenttimemillis();\n        system.out.printf(\u0026quot;%s, %s\u0026quot;, nums[indexresult[0]], nums[indexresult[1]]);\n\n        system.out.printf(\u0026quot;\\r\\n 時間花費: %d ms\u0026quot;, end - start);\n
\n

檢視經典面試題:兩數之和

\n\n

之前做 leetcode 的題目一直沒什麼思路,我從課程中學到了如何運用所學理論去思考。

\n下面是今天剛看的題目:滑動視窗的最大值

\n給定乙個陣列 nums,有乙個大小為 k 的滑動視窗從陣列的最左側移動到陣列的最右側。你只可以看到在滑動視窗 k 內的數字。滑動視窗每次只向右移動一位。返回滑動視窗最大值。

\n示例:

\n輸入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3輸出: [3,3,5,5,6,7]

\n解釋:

\n滑動視窗的位置 最大值[1 3 -1] -3 5 3 6 7 31 [3 -1 -3] 5 3 6 7 31 3 [-1 -3 5] 3 6 7 51 3 -1 [-3 5 3] 6 7 51 3 -1 -3 [5 3 6] 7 61 3 -1 -3 5 [3 6 7] 7

\n下面是通過學習後得到的思路:

\n思路:

\n1、根據優先佇列的概念,我們假設乙個大頂堆,那麼一開始的 [1,3,-1],這樣一排列成堆的樣子就是 3 在最上面,-1 在左下角,1 在右下角… 下一步就是 [3,-1,-3] 了,1 就要被擠開了,擠開了也不影響什麼,-3 再加進來就好了。總之我們需要做的是:

\n(1)、維護我們的 heap,也就是刪除離開視窗的元素,加入新的元素。這裡時間複雜度是 logk

\n(2)、max-\u0026gt;top,就是讓結果是堆頂的元素。複雜度是 o(1),最後整體的複雜度是 nlogk。有沒有更好的解法?

\n2、直接用佇列,而且是雙端佇列,也就是兩邊都能進能出的佇列。首先就是入佇列,每次滑動視窗都把最大值左邊小的數給殺死,也就是出隊,後面再滑動視窗進行維護,這樣相當於每乙個數走過場,時間複雜度就是 o(n*1),比思路 1 要小。

\n**如下:

\n\n

希望能學習到更多東西。

\n檢視白板理論講解:滑動視窗的最大值

\n\n

看老師的課程大概一周了,之前看資料結構和演算法懵懵懂懂的,老師結合例項題,一下子清楚很多了,特別是動態規劃哪一課,一下子茅塞頓開。

\n\n刷的一些演算法題。

\n第一步:遞迴 + 暫存

\n

function fib(n)  else if (memo[n])  else \n    return r;\n  }\n
\n

使用這種方法試了下 n=100 的時候直接掛了,效率依然很低。所以接下來第二步:

\n第二步:動態規劃

\n

function fib(n) \n    return f;\n  }\n
\n

其實矩陣相乘效率更高,等我學會了再來更新**,學會了簡單得動態規劃已經很開心了。

\n戳此檢視:讓你茅塞頓開的動態規劃

\n\n

聽完最後一課,突然有點不捨。本來學習演算法的初衷是為了面試,現在發現做題本身就是一種享受。

\n課上學到很多收益終身的思考模式:

\n五種演算法模式:

\n\n

function recursion(level, param1, param2) \n\n  // 處理當前層級的邏輯\n  processdata(level, data);\n\n  // 遞迴\n  recursion(level + 1, p1, p2);\n\n  // 如果需要,反向當前層級\n  reversestate(level);\n}\n
\n

\n

const visited = new set();\nfunction dfs(node, visited) \n  }\n}\n
\n

\n

const visited = new set();\nfunction bfs(grapg, start, end) \n}\n
\n

\n

function binarysearch(arr, x) \n\n    if (x \u0026lt; arr[mid]) \n\n    if (x \u0026gt; arr[mid]) \n  }\n\n  return -1;\n}\n
\n

\n

// 狀態定義\nconst dp = ;\n\n// 初始狀態\ndp[0][0] = x;\ndp[0][1] = y;\n\n// dp 狀態推導\n\nfor (let i = 0; i \u0026lt;= n; i++) \n}\n\nreturn dp[m][n]\n
\n\n

\n\n

課程的結束不是終點,而是起點,加油,開啟自己成為真正工程師的道路。

\n檢視課程回顧:面試切題四件套

\n\n

我是覃超,作為 facebook 早期員工 \u0026amp; 多年面試官,我對各大知名企業演算法面試的考察點和面試套路,有非常清晰的理解以及豐富的第一手經驗。在《演算法面試通關 40 講》這門課程裡,我會幫你建立一套完整的演算法切題思路,通過「白板演練 + **講解」的方式,手把手帶你掌握高效解題套路,徹底理解題目背後的考點,鍛鍊演算法思維,讓你在面試和平時的工作中大顯身手。

\n學完這門課,你將收穫以下四個方面:

\n1、常見演算法知識點理論講解

\n2、高頻面試題目思路剖析

\n3、leetcode 高效解題四步法

\n4、有效提公升演算法面試通過率

\n課程已更新完畢,共 62 講,目前已有超過10000人加入學習,課程廣受好評,期待你的加入!戳我立即訂閱。

\n

一道面試題的思考

在繼承中new和override相同點和區別?看下面的 有乙個基類a,b1和b2都繼承自a,並且使用不同的方式改變了父類方法print 的行為。測試 輸出什麼?為什麼?public void dotest public class a public class b1 a public class b...

面試題 4種陣列去重的方法

陣列去重或者其衍生作為筆試題或者機試題出現的機率也是很大的,寫出的方法越多,則讓面試官覺得你思維越開闊,那麼成功的機率當然就大了。廢話不多說,下面來說說下面我整理的4中陣列去重的方法 方法一 findinarr方法 select方法組合 findinarr 查詢乙個數在當前陣列中是否存在,存在返回t...

一道面試題引發的思考

首先我們給出這道面試題的 以及題目 lista new arraylist list.add 1 list.add 2 for string item list 問 上段 執行會報錯嗎?如果把 1 換成 2 會報錯嗎?為什麼?首先給出答案 上面這段 執行不會報錯。把 1 換成 2 再執行就會報錯。為...