leetcode hot 100-19. 刪除連結串列的倒數第N個節點
阿新 • • 發佈:2020-10-31
19. 刪除連結串列的倒數第N個節點
給定一個連結串列,刪除連結串列的倒數第n個節點,並且返回連結串列的頭結點。
示例:
給定一個連結串列: 1->2->3->4->5, 和 n = 2. 當刪除了倒數第二個節點後,連結串列變為 1->2->3->5.
說明:
給定的 n 保證是有效的。
進階:
你能嘗試使用一趟掃描實現嗎?
思路:
快慢指標,慢指標先走n步,隨後慢指標和快指標同時往後遍歷,遍歷到快指標為空時慢指標所指元素即使倒數第 n 個結點。
劍指offer 14. 連結串列中倒數第 k 個結點的要求與本題幾乎一模一樣,但是這題是要刪除倒數第 n 個結點,而不是直接返回倒數 第 n個結點,所以慢指標移動同時必須記錄下倒數第n個結點的前一個結點。
最後還需要特殊處理如果待刪除的結點是頭結點的情況,即當 pre 指標是null 時,說明待刪除的結點是頭結點,直接返回 head.next
1 class Solution { 2 public ListNode removeNthFromEnd(ListNode head, int n) { 3 4 ListNode fast = head, slow = head; 5 for(int i = 0; i < n; i++){ 6 if(fast == null){ 7 returnleetcode 執行用時:0 ms > 100.00%, 記憶體消耗:36.8 MB > 56.55%null; 8 } 9 fast = fast.next; 10 } 11 ListNode pre = null; 12 while(fast != null){ 13 fast = fast.next; 14 pre = slow; // 記錄slow前一個結點 15 slow = slow.next; 16 } 17 if(pre == null){ // 如果pre為空,說明待刪除的是第一個結點18 return head.next; 19 } 20 pre.next = slow.next; // 否則刪除slow這個結點 21 return head; 22 } 23 }
複雜度分析:
時間複雜度:O(n)。快指標完整的遍歷了一次連結串列,所以時間複雜度為O(n)。 空間複雜度:O(1)。思路二:藉助輔助頭結點
藉助輔助頭結點來代替刪除的是第一個結點時的特別處理,因為需要刪除倒數第 n 個結點,所以需要記錄倒數第 n 個結點的前一個結點,即倒數第 n + 1個結點。所以讓快指標先走 n + 1步,這樣當快指標為空時,慢指標所指結點就是倒數第 n + 1個結點。
前面之所以slow指標不記錄倒數第 n 個結點,而是記錄倒數第 n 結點,是因為擔心連結串列長度剛好是 n, slow指標不好賦初值,如果初值為 null, 那就沒辦法和 fast 一起向下遍歷,如果初值為 head, 但是又擔心連結串列剛好為(n + 1)的情況,這時如果使用 slow == head來判斷待刪除的結點是第一個結點就有問題。
1 class Solution { 2 public ListNode removeNthFromEnd(ListNode head, int n) { 3 ListNode dummyHead = new ListNode(); 4 dummyHead.next = head; 5 ListNode fast = dummyHead, slow = dummyHead; 6 for(int i = 0; i < n + 1; i++){ // 快指標先走 n + 1步 7 if(fast == null){ 8 return null; 9 } 10 fast = fast.next; 11 } 12 while(fast != null){ 13 fast = fast.next; 14 slow = slow.next; 15 } 16 slow.next = slow.next.next; // 否則刪除slow這個結點 17 return dummyHead.next; 18 } 19 }leetcode 執行用時:0 ms > 100.00%, 記憶體消耗:36.1 MB > 91.46%, 空間消耗略小於思路一