力扣19. 删除链表的倒数第 N 个结点
题目来源(力扣):
https://leetcode.cn/problems/remove-nth-node-from-end-of-list/description/
题目描述:
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
基本思路:
1.首先引入虚拟头结点dummyHead,它的下一个节点就是真正的头结点head。即dummyHead->next=head。
这样子做的好处是便于维护head为nullptr的空链表
2.要找到倒数第n个结点,只需要设置2个指针fast、slow,且都指向头节点
fast指针从head往后移动n个位置,移动完毕后,fast和slow之间始终保持距离为n
之后fast和slow一起往后移动,当fast移动到末尾nullptr时,slow就是倒数第n个节点
3.由于要删节点,所以实际上slow要停留在倒数第n+1个位置。
在《代码随想录》中,作者采用的方法是直接让fast和slow间隔n+1个位置,这是直观且可行的。
我这里采用的方法是,让fast停留在末尾节点而非nullptr(体现在代码中就是while(fas->next)而非while(fas)),从而实现slow停留在倒数n+1的位置上。
我的代码如下:
代码实现:
/*
//ListNode 定义
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(0);
dummyHead->next = head;
ListNode *fas = dummyHead, *slo = dummyHead;
while (n--)
{
fas = fas->next;
}
while (fas->next)
{
fas = fas->next;
slo = slo->next;
}
ListNode *tmp = slo->next;
slo->next = slo->next->next;
delete tmp;
return dummyHead->next;
}
};
《代码随想录》中的写法:
class Solution
{
public:
ListNode *removeNthFromEnd(ListNode *head, int n)
{
ListNode *dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode *fas = dummyHead, *slo = dummyHead;
while (n--)
{
fas = fas->next;
}
fas = fas->next; // 相当于移动n+1步
while (fas)
{ // 这里就要写fas!=nullptr了 简写为while(fas)
fas = fas->next;
slo = slo->next;
}
ListNode *tmp = slo->next;
slo->next = slo->next->next;
delete tmp;
return dummyHead->next;
}
};
时间复杂度
O(n),n为链表中节点总个数,时间主要花费在找到倒数第n-1个节点的位置上
而删除操作时间复杂度O(1),因为只是进行了指针的简单操作而已
实际上,链表中完成一个节点的删除、增加操作时间复杂度都是O(1),主要的时间都花费在找节点位置上了
浙公网安备 33010602011771号