# C++實現移除鏈表倒數第N個節點
## 目錄
1. [問題描述](#問題描述)
2. [鏈表基礎回顧](#鏈表基礎回顧)
3. [解法一:兩次遍歷法](#解法一兩次遍歷法)
4. [解法二:雙指針法](#解法二雙指針法)
5. [完整代碼實現](#完整代碼實現)
6. [邊界條件與測試用例](#邊界條件與測試用例)
7. [復雜度分析](#復雜度分析)
8. [應用場景](#應用場景)
9. [總結](#總結)
## 問題描述
給定一個單向鏈表,要求刪除鏈表的倒數第N個節點,并返回鏈表的頭節點。例如:
輸入:1->2->3->4->5, n = 2
輸出:1->2->3->5
## 鏈表基礎回顧
```cpp
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(nullptr) {}
};
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode dummy(0);
dummy.next = head;
int length = 0;
// 第一次遍歷計算長度
ListNode* curr = head;
while (curr) {
length++;
curr = curr->next;
}
// 定位到待刪除節點的前驅
curr = &dummy;
for (int i = 0; i < length - n; i++) {
curr = curr->next;
}
// 執行刪除
ListNode* toDelete = curr->next;
curr->next = curr->next->next;
delete toDelete; // 防止內存泄漏
return dummy.next;
}
使用快慢指針實現單次遍歷: - 快指針先移動n步 - 然后快慢指針同步移動 - 當快指針到達末尾時,慢指針指向待刪除節點的前驅
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode dummy(0);
dummy.next = head;
ListNode *fast = &dummy, *slow = &dummy;
// 快指針先移動n+1步
for (int i = 0; i <= n; i++) {
fast = fast->next;
}
// 同步移動直到快指針到末尾
while (fast) {
fast = fast->next;
slow = slow->next;
}
// 執行刪除
ListNode* toDelete = slow->next;
slow->next = slow->next->next;
delete toDelete;
return dummy.next;
}
#include <iostream>
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(nullptr) {}
};
class Solution {
public:
// 雙指針法實現
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode dummy(0);
dummy.next = head;
ListNode *fast = &dummy, *slow = &dummy;
for (int i = 0; i <= n; ++i) {
fast = fast->next;
}
while (fast) {
fast = fast->next;
slow = slow->next;
}
ListNode* toDelete = slow->next;
slow->next = slow->next->next;
delete toDelete;
return dummy.next;
}
};
// 輔助函數:打印鏈表
void printList(ListNode* head) {
while (head) {
std::cout << head->val << "->";
head = head->next;
}
std::cout << "nullptr" << std::endl;
}
// 輔助函數:創建測試鏈表
ListNode* createList(std::initializer_list<int> vals) {
ListNode dummy(0);
ListNode* curr = &dummy;
for (int val : vals) {
curr->next = new ListNode(val);
curr = curr->next;
}
return dummy.next;
}
int main() {
Solution solution;
// 測試用例1
ListNode* list1 = createList({1, 2, 3, 4, 5});
std::cout << "Original list: ";
printList(list1);
list1 = solution.removeNthFromEnd(list1, 2);
std::cout << "After removal: ";
printList(list1);
// 測試用例2
ListNode* list2 = createList({1});
list2 = solution.removeNthFromEnd(list2, 1);
printList(list2); // 應輸出 nullptr
return 0;
}
測試用例 | 預期結果 | 說明 |
---|---|---|
[1,2,3,4,5], n=2 | [1,2,3,5] | 常規情況 |
[1], n=1 | [] | 刪除唯一節點 |
[1,2], n=2 | [2] | 刪除頭節點 |
[1,2,3], n=3 | [2,3] | 刪除頭節點 |
[1,2,3,4,5], n=5 | [2,3,4,5] | 刪除頭節點 |
兩次遍歷法:
雙指針法:
關鍵點:掌握快慢指針技巧是解決鏈表問題的關鍵,這種方法可以擴展到許多其他鏈表問題,如檢測環、尋找中點等。 “`
這篇文章提供了約1900字的詳細內容,包含: - 兩種解法的完整實現 - 復雜度分析 - 邊界條件處理 - 實際應用場景 - 可執行的測試代碼 - 標準Markdown格式的排版
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。