因为我学的少,所以用的C语言作答
题目
给你一个链表,删除链表的倒数第n个结点,并返回链表的头结点
C语言解题方法
先画个图,假设删除倒数第2个结点:
(为了便于观看,就假定结点的地址都为图中的0x…)
快慢指针
- 定义两个指针,快指针为p, 慢指针为q。都指向头结点。
-
p先走n(这里是2)步,然后再让p和q同时走。
-
p和q同时走,如果p走到最后一个结点,此时q就在待删除结点的前一结点。
- 这时只需要让
q->next = q->next->next;
就成功把待删除结点删掉了。
代码
函数框架:
struct ListNode* removeNthFromEnd(struct ListNode* head, int n)
{
}
链表结构体:
typedef int ElemType;
typedef struct ListNode
{
ElemType data;
struct ListNode* next;
};
函数实现:
struct Listnode* removeNthFromEnd(struct ListNode* head, int n)
{
assert(head != nullptr);
//快慢指针
ListNode* p = head;
ListNode* q = head;
//先让快指针P走n步
for (int i = 0; i < n; ++i)
{
if (p->next != nullptr)
{
p = p->next;
}
else //这里有个特殊情况,即还没走完n步链表就结束了,那可能要删的就是头结点
{
return head->next; //要删除头结点,那就返回原本头结点的下一个结点
}
}
//让快慢指针同时走,当p走到最后一个结点时,慢指针q正好在待删除结点的前驱
while (p->next != nullptr)
{
p = p->next;
q = q->next;
}
//这一步就删除了倒数第n个结点
p = q->next;
q->next = p->next;
return head;
}
特殊情况
如果在快指针p还没走够n步时,就已经走到最后一个结点(即p->next为nullptr),那说明待删除结点为头结点,那我们返回head->next即可。
在函数的第一步断言时候,就应该判断n的情况,要满足n >= 0 && n <= Get_Length(head); 即链表结点个数。但我没有实现这个函数,就没有写这步断言。。。。