翩若驚鴻,婉若游龍。榮曜秋菊,華茂春鬆。
文章首發於公衆號 「蘑菇睡不着」,更多精彩內容歡迎關注
給你一個鏈表,刪除鏈表的倒數第 n 個結點,而且返回鏈表的頭結點。 node
示例 1:學習
輸入:head = [1,2,3,4,5], n = 2 輸出:[1,2,3,5]
示例 2:指針
輸入:head = [1], n = 1 輸出:[]
示例 3:code
輸入:head = [1,2], n = 1 輸出:[1]
提示:
鏈表中結點的數目爲 sz
1 <= sz <= 30
0 <= Node.val <= 100
1 <= n <= szrem
這道題的包含兩個問題:一是:怎麼找到倒數第 N 個節點;二是:怎麼刪除一個節點。
先說怎麼刪除一個節點吧。其實也很簡單,那就是要被刪除節點的前置節點的next指針,指向被刪除節點的下一個節點便可。代碼片斷爲:node.next = node.next.next;其中 node 爲 被刪除節點的前置節點。
再說說怎麼找到倒數第 N 個節點。這個就有講頭了,主要有兩種方法:io
接下來會用兩端代碼來實現這兩種方法。ast
方法一:class
class Solution { public ListNode removeNthFromEnd(ListNode head, int n) { if (head == null) { return head; } // 定義啞節點,主要是爲了防止當 頭節點也被刪除的狀況 ListNode listNode = new ListNode(0, head); // 快指針 ListNode fast = listNode; // 慢指針 ListNode slow = listNode; // 快指針先走 N 步 while(n > 0 && fast.next != null) { fast = fast.next; n --; } if (n > 0) { return listNode.next; } // 快慢指針一塊兒走 while(fast.next != null) { fast = fast.next; slow = slow.next; } // 若是說被刪除節點是倒數第一個節點,那麼就直接置爲null if (slow.next == null || slow.next.next == null) { slow.next = null; return listNode.next; } // 刪除節點 slow.next = slow.next.next; return listNode.next; } }
時間複雜度:O(n),其中 n 是鏈表的長度,要遍歷一次鏈表
空間複雜度:O(1)。List
方法二:遍歷
class Solution { public ListNode removeNthFromEnd(ListNode head, int n) { ListNode dummy = new ListNode(0, head // 定義棧 Deque<ListNode> stack = new LinkedList<ListNode>(); ListNode cur = dummy; // 按順序壓入棧 while (cur != null) { stack.push(cur); cur = cur.next; } // 彈出 N 個元素 for (int i = 0; i < n; ++i) { stack.pop(); } // 在彈出一個(注意這裏是彈出但不刪除節點),做爲被刪除節點的前置節點 ListNode prev = stack.peek(); // 刪除節點 prev.next = prev.next.next; ListNode ans = dummy.next; return ans; } }
時間複雜度:O(n),其中 n 是鏈表的長度,要遍歷一次鏈表
空間複雜度: O(n),其中 n 是鏈表的長度。主要爲棧的開銷
這道題總體難度還能夠,難點就是要知道如何正確的刪除節點,以及若是正確的找到被刪除的節點。其實刪除節點還有不少辦法,好比:將被刪除節點的next節點的值賦給本身,而後將被刪除節點的next節點刪除也能夠到達所要的效果。
來公衆號:蘑菇睡不着,你們一塊兒學習!