電話面試演算法問答記錄
問:一個陣列,先遞增後遞減,要返回最大的一個數,怎麼實現?
答:依次遍歷第i個數,如果第i個數大於第i + 1個數,那麼返回第i個數,這個數就是最大值。(這麼簡單,大一學生都會)
問:還能優化嗎?
答:啊。。。。。。
(比o(n)時間複雜度還快的演算法就是o(logn),那應該就是二分法,關鍵是怎麼判斷一個數是否是最大的那個數觀察陣列,1 2 3 4 5 4 3,如果如果第i個數小於第i + 1個數,那麼說明第i個數在遞增那部分,最大數在後半部分,我們縮小一半範圍再去後半部分找最大數,如果第i個數大於第i + 1個數那麼他有可能就是最大數,也有可能在遞減那部分,如果在遞減那部分,說明最大數在前半部分,我們縮小一半範圍再去前半部分找最大數。但是如何判斷是否就是最大數呢?那就再增加一個判斷條件。我們看第i個數,第i - 1個數,第i + 1個數三個數的規律。如果三個數依次遞增,那麼第i個數就在遞增部分,如果三個數依次遞減,那麼第i個數就在遞減部分,如果三個數依次先增後減,那麼第i個數就是最大數。)
使用二分法查詢,設中間數下表為i,如果第i個數大於第i - 1個數並且第i + 1個數大於第i個數,那麼第i個數處於遞增序列部分,使用後半部分陣列繼續進行查詢;如果第i個數小於第i - 1個數且第i + 1個數大於第i個數,那麼第i個數處於遞減序列部分,使用前半部分陣列繼續進行查詢;如果第i個數大於第i - 1個數並且第i個數大於第i + 1個數,那麼這個數就是最大數。
問:時間複雜度多少?
答:logn。
問:你筆試那道三數之和題(給一個無序陣列和一個目標值,判斷陣列中能否找到三個數,使三個數之和為目標值)怎麼做的,時間複雜度多少?
答:那個用了HashMap將陣列的數key = 值,value = 值第下表方式全部儲存進去,然後用一個二重迴圈,一層i迴圈一層j迴圈,判斷HashMap中是否含有(目標值 - 第i個數 - 第j個數)。時間複雜度是o(n^2)。
問:還有別的方法嗎?
答:啊。。。。。。
(對於一個無序陣列,先快排成一個有序陣列,時間複雜度為o(nlogn),然後定義三個指標i,j,k初始別為0,如果第i個數 + 第j個數 + 第k個數小於目標數,那麼就k++,如果第i個數 + 第j個數 + 第k個數大於目標數,那麼再將k++就沒有意義了,那麼就去去移動j,不對,這麼做時間複雜度還是n^3,無非是在做剪枝工作。再想想。
對於一個固定的i,如果初始化j 和 k為一個接近的值,那麼就可以更快了。有了,固定i為0,設j為1,k為最大下標值n - 1,如果第i個數 + 第j個數 + 第k個數大於目標值,那麼就將j++,如果第i個數 + 第j個數 + 第k個數小於目標值,那麼就將k--,當k == j時跳出迴圈
將i++再次進行判斷)。
設三個指標i = 0;j = i + 1;k = n - 1;固定i,對於尋找第二個數和第三個數使用雙指標方式,如果三個指標對應數之和小於目標數,就將j指標向後移動一位,如果三個指標對應數之和大於目標數,就講k指標向前移動一位。如果j == k。那麼就跳出迴圈,將i++,接著進行判斷。這樣時間複雜度為o(n^2)。
問:還有別的方法嗎?
答:(面試官你別太過分!)想不到了。
總結
演算法題其實大體方法比較固定,比如說關於陣列部分,可以用HashMap,二分法,雙指標等方法優化時間複雜度。但是並不是單純的靠你會不會這些方法,而是考察你能否在這些方法的基礎上根據題目要求進行略微修改,比如說第一個演算法題,他用到了二分法,但是
判斷條件和縮小後半部分和縮小前半部分要根據題目要求自己思考。
再比如如給一個有序陣列和一個目標值,返回陣列中大於目標值的最小數用二分法,也是對二分法的改變。
第二道演算法題用到了雙指標,但是是在一層迴圈裡使用雙指標查詢。