题目描述
给你一个链表,删除链表的倒数第 n
个结点,并且返回链表的头结点。
示例 1:
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
示例 2:
输入:head = [1], n = 1
输出:[]
示例 3:
输入:head = [1,2], n = 1
输出:[1]
提示:
- 链表中结点的数目为
sz
1 <= sz <= 30
0 <= Node.val <= 100
1 <= n <= sz
进阶:你能尝试使用一趟扫描实现吗?
思路
求的是倒数第n个节点,笔者想到了双指针法。设置一快一慢两个指针,先让快指针移动n步,再让两个指针同时向后移动,当快指针指向空时,慢指针指向的就是倒数第n个节点,此时再删除慢指针指向的节点即可。在删除节点时需要知道该节点的前一个节点,因此这里使用虚拟头节点会更方便。
为了让慢指针最终指向需要删除元素的前一位,快指针可以先移动n+1步,再让两指针同时移动。
代码
C++版:
/**
* 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* dummyHead=new ListNode(); // 定义虚拟头节点
dummyHead->next=head;
ListNode* cur=head;
ListNode* tail=head;
ListNode* pre=dummyHead; // pre指针需要指向待删除节点的上一个节点
while(n-- && tail!=nullptr){
tail=tail->next;
}
while(tail!=nullptr){
tail=tail->next;
cur=cur->next;
pre=pre->next;
}
// 删除节点
pre->next=cur->next;
delete cur;
return dummyHead->next;
}
};
Python版:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
dummyHead=ListNode()
dummyHead.next=head
tail=head
cur=head
pre=dummyHead
for i in range(1,n+1):
tail=tail.next
while tail!=None:
tail=tail.next
cur=cur.next
pre=pre.next
pre.next=cur.next # 删除节点
return dummyHead.next