本篇延續上一篇劍指offer題目系列二,介紹《劍指offer》第二版中的四個題目:O(1)時間內刪除鏈表結點、鏈表中倒數第k個結點、反轉鏈表、合併兩個排序的鏈表。一樣,這些題目並不是嚴格按照書中的順序展現的,而是按本身學習的順序,每一個題目包含了分析和代碼。html
九、O(1)時間內刪除鏈表結點node
題目:微信
在O(1)時間內刪除鏈表結點。給定單鏈表的頭指針和一個結點指針,定義一個方法在O(1)時間內刪除該結點。學習
單鏈表的定義以下:spa
解答:指針
單向鏈表刪除一個結點,最直觀的想法是從鏈表的頭結點開始順序遍歷查找要刪除的結點,而後刪除該結點,這種作法的時間複雜度爲O(n),顯然不知足本題要求。若是咱們把下一個結點的信息複製到要刪除的結點上,覆蓋原有內容,再把下一個結點刪除,這樣就至關於把該結點刪除了,本題解法基於這種方式。htm
首先把要刪除的結點(i)的下一個結點(j)的信息複製到結點i,而後把i指向它的下下個結點(即j的下一個結點),而後再把結點j刪除,這樣就把i刪除了。有兩個特殊狀況:若是要刪除的結點i所在的鏈表中只有一個結點,那麼將其置空(null)便可;若是要刪除的結點i是鏈表尾部的最後一個結點,這就須要從鏈表的頭結點開始,順序遍歷鏈表到該結點,而後將其置空(null),完成刪除。blog
代碼:排序
能夠看到,刪除頭結點和中間結點的時間複雜度爲O(1),而刪除尾結點的時間複雜度爲O(n),但總的平均時間複雜度仍是O(1),符合要求。遞歸
十、鏈表中倒數第k個結點
題目:
輸入一個鏈表,輸出該鏈表中倒數第k個結點。按大多數人的習慣,設鏈表的尾結點爲倒數第一個結點。
單鏈表的定義以下:
解答:
本題採用快慢指針的思想,能夠定義兩個指針。第一個指針從鏈表的頭結點開始遍歷k-1個結點,第二個指針保持不動;當第一個結點遍歷到第k個結點時,第二個結點從鏈表的頭結點開始遍歷,兩個指針的距離始終保持k-1。當第一個指針遍歷到鏈表的尾結點時,此時第二個指針所在的位置正是倒數第k個結點的位置。須要注意的是鏈表不能爲空(null),同時k不能大於鏈表長度。
代碼:
十一、反轉鏈表
題目:
定義一個方法,輸入一個鏈表的頭結點,反轉該鏈表並輸出反轉後鏈表的頭結點。
單鏈表的定義以下:
解答:
本題須要知道三個結點,即當前結點(node)、當前結點的前一個結點(preNode)、當前結點的下一個結點(nextNode)。
反轉時,將當前結點(node)的下一個結點指向其前一個結點(preNode),這樣當前結點(node)與其原來的下一個結點(nextNode)之間發生了斷裂,因此須要保存其原來的下一個結點(nextNode)信息。而後將當前結點賦值給前一個結點(preNode),下一個結點賦值給當前結點……以此類推,直到下一個結點爲空,此時當前結點就是反轉後鏈表的頭結點。
代碼:
十二、合併兩個排序的鏈表
題目:
輸入兩個遞增排序的鏈表,合併這兩個鏈表並使新鏈表中的結點仍然是遞增排序的。
例如:輸入鏈表1:1->3->5->7
鏈表2:2->4->6->8
返回鏈表:1->2->3->4->5->6->7->8
單鏈表的定義以下:
解答:
本題採用遞歸方法,利用歸併的思想。
首先定義一個新鏈表(newList),存放合併後的數據。而後分別遍歷兩個鏈表(list1和list2)的頭結點,比較其大小。若是list1的頭結點小於等於list2的頭結點,則將list1的頭結點添加到新鏈表中(newList),而後將list1頭結點的下一個結點與list2的頭結點做爲參數,執行本方法(即遞歸);反過來若是list1的頭結點大於list2的頭結點,則將list2的頭結點添加到新鏈表中(newList),而後將list1的頭結點與list2頭結點的下一個結點做爲參數,執行本方法(即遞歸)……以此類推,不斷遞歸,直到list1或list2爲空,而後將另外一個列表剩餘結點直接放到新鏈表中便可。
例如題目中兩個鏈表第一次比較時,list1的頭結點1小於list2的頭結點2,故list1頭結點1放入newList中;而後list1頭結點的下一個結點3大於list2的頭結點2,故list2頭結點2放入newList中;而後list1頭結點的下一個結點3小於list2頭結點的下一個結點4,故list1頭結點的下一個結點3放入newList中……
代碼:
轉載請註明出處 http://www.cnblogs.com/Y-oung/p/8933438.html
工做、學習、交流或有任何疑問,請聯繫郵箱:yy1340128046@163.com 微信:yy1340128046