题目:给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
给定的 n 保证是有效的。
进阶:
你能尝试使用一趟扫描实现吗?
题解
普通思路:如上列链表. l->length == 5. 且倒数第2个数的ind == 3, 则需要删除的是下标ind == 3的节点.
【注意】以下两种情况要进行特殊处理
情况一:当链表只有一个节点
情况二:要删除的节点是头结点
代码演示:
struct ListNode* erase(struct ListNode* head, int ind, int length) {
struct ListNode *p = head;
if (ind == 0) {
head = head->next;
free(p);
return head;
}
while (--ind) {
p = p->next;
if (p == NULL) return head;
}
struct ListNode *q = p->next;
p->next = q->next;
free (q);
return head;
}
struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
struct ListNode *p = head;
int length = 0;
while (p) {
length++;
p = p->next;
}
int ind = length - n;
head = erase(head, ind, length);
return head;
}
进阶思路:f,s 的起始位置是虚拟节点○,让f 先走 n 步,然后s与f再同时往后走。直到当f -> next == NULL 时,s -> next 即为要删除的点。
- 设虚拟头结点方便处理普通思路需要注意的两种情况
s,f
○ -> 口->口->口->口->口
虚拟节点 head
------------------------------------------------------------------
当n = 2:
s f
○ -> 口->口->口->口->口
free(s)即为所求
代码演示:
struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
struct ListNode ret, *f, *s;
ret.next = head;
f = s = &(ret);
while (n--) {
f = f->next;
}
while (f->next != NULL) {
f = f->next;
s = s->next;
}
f = s->next;
s->next = f->next;
free(f);
return ret.next;
}