您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# 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进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。