力扣19. 删除链表的倒数第N个节点(两次遍历、加间隔一次遍历)
https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
给定的 n 保证是有效的。
进阶:
你能尝试使用一趟扫描实现吗?
一、两个遍历
复杂度分析
时间复杂度:O(L),该算法对列表进行了两次遍历,首先计算了列表的长度 L 其次找到第 (L - n)个结点。 操作执行了 2L−n 步,时间复杂度为 O(L)。
空间复杂度:O(1),我们只用了常量级的额外空间
ListNode* removeNthFromEnd(ListNode* head, int n)
{
//鲁棒性,链表为空
if (head==nullptr || n<=0)
{
return head;
}
//获取链长
ListNode* temp = head;
int len = 0;
while (temp != nullptr)
{
len++;
temp = temp->next;
}
//刚好删的是第一个节点
if (n==len)
{
return head->next;
}
//cur指针去到要删的节点前一个节点
ListNode* cur = head;
for (int i = 0; i<len - n-1; i++)
{
cur = cur->next;
}
//删除操作
ListNode* del = cur->next;
cur->next = del->next;
return head;
}
二、加间隔一次遍历
图来自一位大神,可以关注他的公众号
ListNode* removeNthFromEnd(ListNode* head, int n)
{
//鲁棒性,链表为空
if (head == nullptr || n <= 0)
{
return head;
}
ListNode* p = head;
ListNode* q = head;
for (int i = 0; i <= n; i++)
{
q = q->next;
}
while (q != nullptr)
{
p = p->next;
q = q->next;
}
//删除操作
p->next = p->next->next;
return head;
}
三、汇总
#include "stdafx.h"
struct ListNode
{
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class Solution
{
public:
ListNode* removeNthFromEnd2(ListNode* head, int n)
{
//鲁棒性,链表为空
if (head == nullptr || n <= 0)
{
return head;
}
//获取链长
ListNode* temp = head;
int len = 0;
while (temp != nullptr)
{
len++;
temp = temp->next;
}
//刚好删的是第一个节点
if (n == len)
{
return head->next;
}
//cur指针去到要删的节点前一个节点
ListNode* cur = head;
for (int i = 0; i < len - n - 1; i++)
{
cur = cur->next;
}
//删除操作
ListNode* del = cur->next;
cur->next = del->next;
return head;
}
ListNode* removeNthFromEnd1(ListNode* head, int n)
{
//鲁棒性,链表为空
if (head == nullptr || n <= 0)
{
return head;
}
ListNode* p = head;
ListNode* q = head;
for (int i = 0; i <= n; i++)
{
q = q->next;
}
while (q != nullptr)
{
p = p->next;
q = q->next;
}
//删除操作
p->next = p->next->next;
return head;
}
};
int main()
{
Solution s;
ListNode head[5] = { 1,2,3,4,5 };
head[0].next = &head[1];
head[1].next = &head[2];
head[2].next = &head[3];
head[3].next = &head[4];
auto result1 = s.removeNthFromEnd1(head, 2);
return 0;
}