每天一道LeetCode-----刪除連結串列倒數第n個節點
阿新 • • 發佈:2019-01-10
原題連結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;
}
};