前幾天有個朋友去面試位元組跳動,面試官問了他一道鍊錶相關的演算法題,不過他一時之間沒做出來,就來問了我一下,感覺這道題還不錯,拿來講一講。
#題目
這其實是一道變形的鍊錶反轉題,大致描述如下
給定乙個單鏈表的頭節點 head,實現乙個調整單鏈表的函式,使得每k個節點之間為一組進行逆序,並且從鍊錶的尾部開始組起,頭部剩餘節點數量不夠一組的不需要逆序。(不能使用佇列或者棧作為輔助)
例如:
鍊錶:1->2->3->4->5->6->7->8->null, k = 3。那麼 6->7->8,3->4->5,1->2各位一組。調整後:1->2->5->4->3->8->7->6->null。其中 1,2不調整,因為不夠一組。
# 解答
這道題的難點在於,是從鍊錶的尾部開始組起的,而不是從鍊錶的頭部,如果是頭部的話,那我們還是比較容易做的,因為你可以遍歷鍊錶,每遍歷 k 個就拆分為一組來逆序。但是從尾部的話就不一樣了,因為是單鏈表,不能往後遍歷組起。不過這道題肯定是用遞迴比較好做,對遞迴不大懂的建議看我之前寫的一篇文章為什麼你學不會遞迴?告別遞迴,談談我的一些經驗,這篇文章寫了關於遞迴的一些套路。
先做一道類似的反轉題
在做這道題之前,我們不仿先來看看如果從頭部開始組起的話,應該怎麼做呢?例如:鍊錶:1->2->3->4->5->6->7->8->null, k = 3。調整後:3->2->1->6->5->4->7->8->null。其中 7,8不調整,因為不夠一組。
對於這道題,如果你不知道怎麼逆序乙個單鏈表,那麼可以看一下我之前寫的如何優雅著反轉單鏈表
這道題我們可以用遞迴來實現,假設方法reverseknode()的功能是將單鏈表的每k個節點之間逆序(從頭部開始組起的哦);reverse()方法的功能是將乙個單鏈表逆序。
那麼對於下面的這個單鏈表,其中 k = 3。
我們把前k個節點與後面的節點分割出來:
temp指向的剩餘的鍊錶,可以說是原問題的乙個子問題。我們可以呼叫reverseknode()方法將temp指向的鍊錶每k個節點之間進行逆序。再呼叫reverse()方法把head指向的那3個節點進行逆序,結果如下:
接著,我們只需要把這兩部分給連線起來就可以了。最後的結果如下:
**如下:
//k個為一組逆序回到本題public listnode reversekgroup(listnode head, int k) //判斷節點的數量是否能夠湊成一組 if(temp == null) return head; listnode t2 = temp.next; temp.next = null; //把當前的組進行逆序 listnode newhead = reverselist(head); //把之後的節點進行分組逆序 listnode newtemp = reversekgroup(t2, k); // 把兩部分連線起來 head.next = newtemp; return newhead; } //逆序單鏈表 private static listnode reverselist(listnode head)
這兩道題可以說是及其相似的了,只是一道從頭部開始組起,這道從頭部開始組起的,也是 leetcode 的第 25 題。而面試的時候,經常會進行變形,例如這道位元組跳動的題,它變成從尾部開始組起,可能你一時之間就不知道該怎麼弄了。當然,可能有人一下子就反應出來,把他秒殺了。
其實這道題很好做滴,你只需要先把單鏈表進行一次逆序,逆序之後就能轉化為從頭部開始組起了,然後按照我上面的解法,處理完之後,把結果再次逆序即搞定。兩次逆序相當於沒逆序。
例如對於鍊錶(其中 k = 3)
我們把它從尾部開始組起,每 k 個節點為一組進行逆序。步驟如下
1、先進行逆序
逆序之後就可以把問題轉化為從頭部開始組起,每 k 個節點為一組進行逆序。
2、處理後的結果如下
3、接著在把結果逆序一次,結果如下
**如下
public listnode solve(listnode head, int k)類似於這種需要先進行逆序的還要兩個鍊錶相加,這道題位元組跳動的筆試題也有出過,如下圖的第二題
這道題就需要先把兩個鍊錶逆序,再節點間相加,最後在合併了。
# 總結
位元組跳動面試題
位元組跳動面試題 http協議 http協議是乙個應用層的協議,由請求和響應構成,使用統一資源識別符號來傳遞資料和建立連線 一次http請求的基本流程一般是,在建立tcp連線後,由客戶端向服務端發起一次請求 request 而伺服器在接收到以後返回給客戶端乙個響應 response 所以我們看到的h...
位元組跳動面試題
假如有兩台伺服器 server1和server2 這兩台伺服器上分別部署了相同的前端靜態檔案,index.html index.js 如果server1中的靜態資源被更新了,那麼此時會出現什麼問題?如何解決?通過控制 伺服器,讓客戶無感平滑公升級 root 當前頁面共有 files.length 個...
位元組跳動面試題
1 請分析以下 執行結果 async function a return result var p a p.abort 2 手寫乙個節流函式 手寫節流函式3 什麼是裝箱和拆箱 裝箱和拆箱操作,能夠在值型別和引用型別中架起一做橋梁。換言之,可以輕鬆的實現值型別與引用型別的互相轉換。裝箱是將值型別轉換為...