如何删除?
- 找到倒数第n个节点的 前置(倒数n+1)节点 和 后置(倒数n-1)节点
- 让目标节点的前置节点 指向 目标节点的后置节点
- 但是头节点没有前置节点怎么办?加一个空节点指向head就可以了
暴力遍历
- 为什么使用hair?因为被删除的可能是head节点呀
- 获取链表长度length
- 找到目标节点的前置节点,即第length-n个节点
- 前置节点指向后置节点
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;}tmp = hair;for(int i=0;i<length-n;i++){tmp = tmp->next;}tmp->next = tmp->next->next;return hair->next;}
};
栈
- 入栈,从空节点开始(不然删除头节点,出栈时找不到头节点的前置节点)
- 出栈n+1个节点,最后一个出栈的就是目标节点的前置节点
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停留的位置就是要删除节点的前置节点
class Solution {
public:ListNode* removeNthFromEnd(ListNode* head, int n) {ListNode* hair = new ListNode(-1,head); ListNode* first = head; ListNode* second = hair; for(int i=0;i<n;i++) {first = first->next;}while(first) {second = second->next;first = first->next;}second->next = second->next->next;return hair->next;}
};