LeetCode[19] 删除链表的倒数第 N 个结点
如何删除?
- 找到倒数第n个节点的 前置(倒数n+1)节点 和 后置(倒数n-1)节点
- 让目标节点的前置节点 指向 目标节点的后置节点
- 但是头节点没有前置节点怎么办?加一个空节点指向head就可以了
暴力遍历
- 为什么使用hair?因为被删除的可能是head节点呀
- 获取链表长度length
- 找到目标节点的前置节点,即第length-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) {
ListNode* hair = new ListNode(-1,head);
ListNode* tmp = head;
// 获取链表长度
int length = 0;
while(tmp)
{
length++;
tmp = tmp->next;
}
// 找到第length-n个节点
tmp = hair;
for(int i=0;i<length-n;i++)
{
tmp = tmp->next;
}
tmp->next = tmp->next->next;
return hair->next;
}
};
栈
- 入栈,从空节点开始(不然删除头节点,出栈时找不到头节点的前置节点)
- 出栈n+1个节点,最后一个出栈的就是目标节点的前置节点
/**
* 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) {
ListNode* hair = new ListNode(-1,head);
ListNode* tmp = hair;
stack<ListNode*> mystack;
while(tmp)// 入栈
{
mystack.push(tmp);
tmp = tmp->next;
}
for(int i=0;i<=n;i++) // 出栈
{
tmp = mystack.top();
mystack.pop();
}
tmp->next = tmp->next->next;
return hair->next;
}
};
双指针
- 建立一个空节点,指向头节点,可会快速返回头节点
- 指针1赋值为头节点,指针2赋值为hair节点 (为了能够停在前置节点)
- 指针1先走n步
- 指针1和指针2同时移动,直到指针1为空,即到链表尾部
- 此时指针2停留的位置就是要删除节点的前置节点
/**
* 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) {
ListNode* hair = new ListNode(-1,head); // 空节点指向头节点
ListNode* first = head; // 指针1
ListNode* second = hair; // 指针2
for(int i=0;i<n;i++) // 指针1先行移动n次
{
first = first->next;
}
while(first) // 指针1和指针2同时移动
{
second = second->next;
first = first->next;
}
// 第n个节点的前置节点指向第n个节点的后置节点
second->next = second->next->next;
return hair->next;
}
};