- 題目描述:刪除鏈表的倒數第N個節點
給定一個鏈表,刪除鏈表的倒數第 n 個節點,並且返回鏈表的頭結點。
示例:
給定一個鏈表: 1->2->3->4->5, 和 n = 2.
當刪除了倒數第二個節點後,鏈表變爲 1->2->3->5.
說明:
給定的 n 保證是有效的。
進階:
你能嘗試使用一趟掃描實現嗎?
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
- C++編程實現:
(1)方法一:
兩次遍歷算法
思路
我們注意到這個問題可以容易地簡化成另一個問題:刪除從列表開頭數起的第(L - n + 1)個結點,其中L是列表的長度。
只要我們找到列表的長度L,這個問題就很容易解決。
算法
首先我們將添加一個啞結點作爲輔助,該結點位於列表頭部。啞結點用來簡化某些極端情況,例如列表中只含有一個結點,
或需要刪除列表的頭部。在第一次遍歷中,我們找出列表的長度L。然後設置一個指向啞結點的指針,並移動它遍歷列表,
直至它到達第(L−n)個結點那裏。我們把第(L−n)個結點的 next 指針重新鏈接至第 (L−n+2) 個結點,完成這個算法。
作者:LeetCode
鏈接:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/solution/shan-chu-lian-biao-de-dao-shu-di-nge-jie-dian-by-l/
來源:力扣(LeetCode)
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。
/**
* 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* dummy = new ListNode(0);
dummy->next = head;
int nlength = 0;
ListNode* first = head;
while(first)
{
nlength++;
first = first->next;
}
nlength -= n;
first = dummy;
while(nlength>0)
{
nlength--;
first = first->next;
}
first->next = first->next->next;
return dummy->next;
}
};
複雜度分析:
時間複雜度:O(L),該算法對列表進行了兩次遍歷,首先計算了列表的長度L其次找到第(L−n)個結點。 操作執行了2L−n步,時間複雜度爲O(L)。
空間複雜度:O(1),我們只用了常量級的額外空間。
(2)方法二:
算法
上述算法可以優化爲只使用一次遍歷。我們可以使用兩個指針而不是一個指針。第一個指針從列表的開頭向前移動 n-1步後,
判斷結點next是否到達末尾,如果到達末尾則需要刪除的是第一個元素,直接返回head->next就行了;如果結點next沒有
到達末尾,第二個指針將從列表的開頭出發。現在,這兩個指針被n個結點分開。我們通過同時移動兩個指針向前來保持這
個恆定的間隔,直到第一個指針到達最後一個結點。此時第二個指針將指向從最後一個結點數起的第n個結點。我們重新鏈
接第二個指針所引用的結點的 next 指針指向該結點的下下個結點。
作者:LeetCode
鏈接:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/solution/shan-chu-lian-biao-de-dao-shu-di-nge-jie-dian-by-l/
來源:力扣(LeetCode)
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。
/**
* 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* forward = head;
ListNode* backward = head;
for (int i=0; i<n-1; i++)
forward = forward->next;
if (forward->next == NULL)
return head->next;
forward = forward->next;
while(forward->next)
{
forward = forward->next;
backward = backward->next;
}
backward->next = backward->next->next;
return head;
}
};
複雜度分析
時間複雜度:O(L),該算法對含有L個結點的列表進行了一次遍歷。因此時間複雜度爲O(L)。
空間複雜度:O(1),我們只用了常量級的額外空間。