1. 程式人生 > >LeetCode 19:刪除連結串列的倒數第N個節點 Remove Nth Node From End of List

LeetCode 19:刪除連結串列的倒數第N個節點 Remove Nth Node From End of List

給定一個連結串列,刪除連結串列的倒數第 n 個節點,並且返回連結串列的頭結點。

Given a linked list, remove the n-th node from the end of list and return its head.

示例:

給定一個連結串列: 1->2->3->4->5, 和 n = 2.

當刪除了倒數第二個節點後,連結串列變為 1->2->3->5.

說明:

給定的 n 保證是有效的。

Note:

Given n will always be valid.

進階:

你能嘗試使用一趟掃描實現嗎?

Follow up:

Could you do this in one pass?

解題思路:

這道題很有意思,雖然很簡單,但是很考驗一個人的思維。最先想到的方法就是遍歷整個連結串列得到長度,減去 n 得到實際應該刪除的節點的位置了。然而由於單鏈表刪除操作的特殊性,得到位置之後仍然需要再遍歷一次來刪除該節點。

進階要求是一次遍歷完成該題,想想是否有好的方法?

假設連結串列長度為 L ,定義一個指標先走 n 步,此時該指標還剩下 L-n 個節點即可完成該連結串列的遍歷。而第 L-n 個節點不就是題目要求的的要刪除的倒數第 n 個節點嗎?這時候只需要再定義一個指標,讓它與之前的指標同時遍歷,當第一個指標遇到空節點時(null 節點),該指標即指向刪除的節點。

值得注意的的是,指向應當刪除的節點並無法刪除它,應當指向該刪除節點的前一個節點。

Java:

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode curA = head;
        ListNode curB = head;
        for (int i = 0; i < n; i++) curA = curA.next;
        if (curA == null) {//如果走了n步之後該節點指向空節點,則該連結串列只有一個節點
            head = head.next;
            return head;
        }
        while (curA.next != null) {//當第一個指標的下一個節點為空時,該指標指向最後一個節點,而指標curB 走了L-n-1步,即指向該刪除節點的前一個節點
            curA = curA.next;
            curB = curB.next;
        }
        curB.next = curB.next.next;//將本來指向應當刪除節點地址指向應當刪除節點的下一個節點的地址
        return head;
    }
}

Python3:

class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        curA,curB=head,head
        for i in range(n):
            curA=curA.next
        if not curA:
            head=head.next
            return head
        while(curA.next):
            curA=curA.next
            curB=curB.next
        curB.next=curB.next.next

歡迎關注公.眾號一起刷題:愛寫Bug