题目
链接: 删除链表的倒数第n个节点
双指针法的细节
其实就是是不是 使用伪头节点 的问题
访问节点非法
如果不使用伪头节点时,代码为
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
auto l = head;
auto r = head;
for (int i = 0; i < n; ++i) {
r = r->next;
}
while (r->next != nullptr) {
l = l->next;
r = r->next;
}
l->next = l->next->next;
return prehead->next;
}
};
当
n
=
1
n = 1
n=1 即要删除的是最后一个节点时,我们代码中 r == nullptr
即最后一个节点的下一个,此时再判断 r->next
显然是非法的
返回值
此处要求返回头节点,很容易直接返回给出原链表的头节点。但当要删除的节点就是头节点时,返回 head
就是错误的。应当返回伪头节点的 ->next
所以最终的参考代码可以写作
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
auto prehead = new ListNode(0);
prehead->next = head;
auto l = prehead;
auto r = head;
for (int i = 0; i < n; ++i) {
r = r->next;
}
while (r!= nullptr) {
l = l->next;
r = r->next;
}
l->next = l->next->next;
return prehead->next;
}
};
务必注意代码实现中的细节。即便双指针思路已经非常清晰但细节上仍可能犯错。