1. 程式人生 > >每天一道LeetCode-----刪除連結串列倒數第n個節點

每天一道LeetCode-----刪除連結串列倒數第n個節點

原題連結Remove Nth Node From End of List
這裡寫圖片描述
意思是給定一個連結串列,要求刪除倒數第n個節點,返回連結串列頭,複雜度在O(n)

思路就是找到倒數第n個和倒數第n+1個節點即可,僅僅遍歷一遍連結串列的話只需要記錄這兩個節點。
一個節點指向當前遍歷到的節點,記錄和連結串列頭的距離,如果到達n,開始記錄目標節點和目標節點的上一個節點。
以題目例項為例

 (header) |    (head)
|NULL     |     1        |  2        |  3        |  4        |  5        |  NULL        
|tar_node |     cur_node |
| | | | |last_node| | | | | | |---------|------------- |-----------|-----------|-----------|-----------|---------- |tar_node | | cur_node | | | | |last_node| | | | | | |---------|------------- |-----------|-----------|-----------|-----------|---------- |tar_node |
| | cur_node | | | |last_node| | | | | | -------------------------------------------------|-----------|-----------|---------- | | | | | | | |last_node| tar_node |
| cur_node | | | -------------------------------------------------|-----------|-----------|---------- | | last_node| tar_node | | cur_node | | -------------------------------------------------|-----------|-----------|---------- | | | last_node| tar_node | | cur_node | -------------------------------------------------|-----------|-----------|---------- | | | | last_node| tar_node | | cur_node ------------------------------------------------------------------------------------

基本步驟就是這樣(-.-,竟然手動畫了個表格)
tar_node開始移動的時機是cur_node於tar_node的距離大於n,就需要將tar_node後移,始終保持這二者間距離小於等於n。在結束之後將last_node的next指向tar_node的next。
這裡有個邊界條件問題,當要刪除的節點是連結串列頭時,也就是說tar_node是head,此時last_node是NULL,執行last_node->next = tar_node->next會出錯。
有一個小技巧,為連結串列手動增加一個節點header,另header->next = head,此時上面三個節點初始位置都是手動新增的這個節點header,也就是替代了NULL,這樣即使要刪除連結串列頭,那麼last_node也會是header,不再是NULL。
程式碼如下

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        /* 手動新增一個節點,指向連結串列頭,初始三個指標都指向這個新新增的節點 */
        ListNode* header = new ListNode(-1);
        header->next = head;
        ListNode* cur_node = header;
        ListNode* tar_node = header;
        ListNode* tar_last_node = header;
        int node_cnt = 0;
        while(cur_node)
        {
            cur_node = cur_node->next;
            /* 保證cur_node和tar_node的距離始終小於等於n */
            if(++node_cnt > n)
            {
                tar_last_node = tar_node;
                tar_node = tar_node->next;
                node_cnt = n;
            }
        }
        /* 刪除tar_node */
        tar_last_node->next = tar_node->next;
        ListNode* ans = header->next;
        /* 刪除新增的頭部節點 */
        delete header;
        return ans;
    }
};