方法一:暴力破解
**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*
int getLength(struct ListNode* head) {
int length = 0;
while (head) {
++length;
head = head->next;
}
return length;
}
struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
struct ListNode* L= malloc(sizeof(struct ListNode));
L->val = 0;
L->next = head;
int length = getLength(head);
struct ListNode* cur = L;
for (int i = 1; i < length - n + 1; ++i) {
cur = cur->next;
}
cur->next = cur->next->next;
struct ListNode* ans = L->next;
free(L);
return ans;
}
分析:
详细步骤:
-
创建辅助节点:
struct ListNode* L = malloc(sizeof(struct ListNode));
- 分配内存并初始化一个辅助头节点
L
,它的值为0,next
指向原始链表的头节点head
。这有助于简化边界条件处理,例如删除链表的第一个节点。
-
计算链表长度:
int length = getLength(head);
- 调用
getLength
函数获取链表的长度。
-
定位要删除的节点的前一个节点:
struct ListNode* cur = L;
- 从辅助节点开始,使用一个循环移动到要删除节点的前一个节点。
for (int i = 1; i < length - n + 1; ++i) { cur = cur->next; }
- 这个循环定位到倒数第
n
个节点的前一个节点。
-
删除节点:
cur->next = cur->next->next;
- 修改当前节点的
next
指针,使其跳过下一个节点,从而达到删除效果。
-
释放辅助节点并返回结果:
struct ListNode* ans = L->next;
- 获取调整后的链表的新头节点。
free(L);
- 释放辅助头节点占用的内存。
return ans;
- 返回新的链表头节点。
方法二:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
//定义虚拟头节点dummy 并初始化使其指向head
struct ListNode* dummy = malloc(sizeof(struct ListNode));
dummy->val = 0;
dummy->next = head;
//定义 fast slow 双指针
struct ListNode* fast = dummy;
struct ListNode* slow = dummy;
n++;
while(n--&&fast!=NULL)
{
fast=fast->next;
}
while(fast!=NULL)
{
fast=fast->next;
slow=slow->next;
}
slow->next = slow->next->next;//删除倒数第n个节点
free(dummy);//删除虚拟节点dummy
return head;
}