小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
19. 删除链表的倒数第 N 个结点
题目描述
给你一个链表,删除链表的倒数第 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]
图解
双指针:使用快慢指针来解决这个问题,快指针比慢指针先走n步(设置虚拟头节点),之后一起向后遍历,快指针指向最后一个节点时,慢指针指向节点的next节点就是待删除的节点。
CODE
#include <iostream>
using namespace std;
struct ListNode
{
int val;
ListNode *next;
ListNode(int v) : val(v), next(nullptr){};
ListNode(int v, ListNode *next) : val(v), next(next){};
};
class Solution
{
public:
ListNode *removeNthFromEnd(ListNode *head, int n)
{
// 使用虚拟头节点,删除头节点时方便
ListNode *dummpy = new ListNode(0, head);
// 慢指针,指向待删节点的前驱节点
ListNode *pre = dummpy;
// 快指针,指向当前遍历的节点
ListNode *cur = pre->next;
// 快指针先走n步
while (n--)
{
cur = cur->next;
}
// 遍历节点,快指针指向最后一个节点时,遍历完了所有节点
// 慢指针此时指向了待删节点的前一个节点
while (cur != nullptr)
{
cur = cur->next;
pre = pre->next;
}
// 删除节点
ListNode *tmp = pre->next;
pre->next = tmp->next;
delete tmp;
// 返回头节点
return dummpy->next;
}
void printListNode(ListNode *head)
{
ListNode *cur = head;
while (cur)
{
cout << cur->val << " ";
cur = cur->next;
}
cout << endl;
}
};
int main()
{
// 测试代码
ListNode *head = new ListNode(1);
ListNode *p1 = new ListNode(2);
ListNode *p2 = new ListNode(3);
ListNode *p3 = new ListNode(4);
head->next = p1;
p1->next = p2;
p2->next = p3;
Solution solu;
ListNode *newHead = solu.removeNthFromEnd(head, 4);
solu.printListNode(newHead);
return 0;
}