LeetCode筆記:19. Remove Nth Node From End of List

問題:

Given a linked list, remove the nth node from the end of list and return its head.
For example,

Given linked list: 1->2->3->4->5, and n = 2.
After removing the second node from the end, the linked list becomes 1->2->3->5.

Note:
Given n will always be valid.
Try to do this in one pass.

大意:

給出一個鏈表,移除鏈表的倒數第n個節點并返回鏈表頭。
例子,

給出鏈表: 1->2->3->4->5, 以及 n = 2.
在移除倒數第二個節點后,列表變為了 1->2->3->5。

注意:
給出的n一定是有效的。
嘗試在一輪循環中做。

思路:

題目的難點在于你不知道遍歷到第幾個節點時是要刪除的倒數第n個節點。

我的做法很笨,遍歷一遍記錄所有節點的值和位置,然后重新根據值和位置創建新的鏈表,跳過要刪除的那個位置的節點,因為此時知道總節點數了就可以推出是第幾個節點了。在操作時要注意一些特殊情況,比如只有一個節點時、刪除頭結點時要怎么處理。

代碼(Java):

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        int[] nodeVal = new int[100];
        int[] nodeIndex = new int[100];
        nodeVal[0] = head.val;
        nodeIndex[0] = 0;
        int index = 1;
        while (head.next != null) {
            head = head.next;
            nodeVal[index] = head.val;
            nodeIndex[index] = index;
            index++;
        }
        
        ListNode newHead;
        int begin = 0;
        if (index == 1) return null;
        else if (index == n) {
            newHead = new ListNode(nodeVal[1]);
            begin = 1;
        } else newHead = new ListNode(nodeVal[0]);
        ListNode tempNode = newHead;
        for (int i = begin+1; i < index; i++) {
            if (i != index - n) {
                ListNode newNode = new ListNode(nodeVal[i]);
                tempNode.next = newNode;
                tempNode = newNode;
            }
        }
        
        return newHead;
    }
}

他山之石:

public ListNode removeNthFromEnd(ListNode head, int n) {
    
    ListNode start = new ListNode(0);
    ListNode slow = start, fast = start;
    slow.next = head;
    
    //Move fast in front so that the gap between slow and fast becomes n
    for(int i=1; i<=n+1; i++)   {
        fast = fast.next;
    }
    //Move fast to the end, maintaining the gap
    while(fast != null) {
        slow = slow.next;
        fast = fast.next;
    }
    //Skip the desired node
    slow.next = slow.next.next;
    return start.next;
}

看一下這個巧妙的做法,他設了快慢兩個標記,初始都在頭結點,快的先往后遍歷,遍歷到與頭結點相差為n的時候停止,然后快的和慢的一起往后走,直到快的走到了鏈表尾節點打止,這時候快慢兩個節點間相差的節點數正好是n,也就是說慢的所在的下一個節點正好是要刪除的節點,直接跳過去就可以了,一遍遍歷完成,很棒。

合集:https://github.com/Cloudox/LeetCode-Record


查看作者首頁

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容