首先采用了最一般的办法,就是先统计出该链表里面有多少个element,然后再执行一次遍历,遍历到倒数第n个节点的前一个节点,再使用p->next = p->next->next就可以删除倒数第n个节点
但不是one pass实现的,代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
struct ListNode *dummy = malloc(sizeof(struct ListNode));
struct ListNode *p;
int len = 0;
int diff = 0;
dummy->next = head;
//从头开始遍历,找到链表长度
p = head;
while(p != NULL)
{
p = p->next;
len++;
}
//把p指针放回开头dummy处
p = dummy;
diff = len - n;
while(diff--)
{
p = p->next;
}
//删除节点
p->next = p->next->next;
return dummy->next;
}
第二种方法,即one pass:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
struct ListNode *dummy = malloc(sizeof(struct ListNode));
struct ListNode *fast;
struct ListNode *slow;
dummy->next = head;
fast = dummy;
slow = dummy;
//先把fast往后挪n下
while(n--)
{
fast = fast->next;
}
/* 同时挪动fast和slow,直到fast的下一个节点指向NULL,slow就挪到了要删除节点的前一个节点,很巧妙的数学方法,赞 */
while(fast->next != NULL)
{
fast = fast->next;
slow = slow->next;
}
//删除倒数第n个节点
slow->next = slow->next->next;
return dummy->next;
}