给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
进阶:你能尝试使用一趟扫描实现吗?
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
// 方法一 两趟循环 或者用栈也可以,栈和两趟循环类似,不多说了
struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
if (head == NULL) {
return NULL;
}
struct ListNode *tail = head;
int nodeCount = 0;
while (tail != NULL) {
nodeCount++;
tail = tail -> next;
}
if (nodeCount == n) {
tail = head;
head = tail -> next;
free(tail);
tail = NULL;
return head;
}
int i;
tail = head;
for (i = 0; i < nodeCount - n - 1; i++) {
tail = tail -> next;
}
struct ListNode * tmp = tail;
tmp = tail -> next;
tail -> next = tmp -> next;
free (tmp);
tmp = NULL;
return head;
}
// 方法二 快慢双指针 一趟循环,双指针,第一个指针先走 n-1步,然后第二个指针开始走,然后两个指针同时走,等到第一个指针到尾结点,第二个指针刚好在倒数第n个节点,刚好删除掉即可
struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
if (head == NULL) {
return head;
}
struct ListNode * first = head;
struct ListNode * second = head;
int count = 0;
while (first != NULL) {
if (count < n + 1) {
first = first -> next;
count++;
continue;
}
count++;
first = first -> next;
second = second -> next;
}
if (count == n) { // 头结点单独处理
head = second -> next;
free(second);
second == NULL;
return head;
}
first = second -> next;
second -> next = first -> next;
free(first);
first = NULL;
return head;
}