题目:
Given a linked list, remove the nth node from the end of list and return its head.
For example,
Given linked list: 1->2->3->4->5, and n = 2. After removing the second node from the end, the linked list becomes 1->2->3->5.
Note:
Given n will always be valid.
Try to do this in one pass.
思路:使用快慢两个指针,两个指针距离为N,这样当快指针到达List的最后节点时,慢指针就达到了倒数第N个节点。
Attention: 注意考虑只有List只有一个节点的情况。
AC Code:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *removeNthFromEnd(ListNode *head, int n) {
//移除从单链表倒数第N个节点,并返回删除后的单链表头
//双指针,快慢两个指针(front领先n个位置)
if(head == NULL)
return head;
ListNode* dummyhead = new ListNode(0); //创建一个虚拟头结点
dummyhead->next = head; //head不是无意义的头结点,而是链表的第一个节点。*head是指向第一个节点的指针。
ListNode* preback, *front;
preback = dummyhead;
front = head;
//front前进n-1步
for(int i=1; i<n; i++)
{
if(front->next == NULL)
return head;
front = front->next;
}
//front两个指针同时前进,当front指针指向单链表倒数第一个结点时,preback指向倒数第n+1个结点
while(front->next != NULL) //到达最后一个结点前循环 条件: !=
{
front = front->next;
preback = preback->next;
}
//删除preback指向的结点的后一个结点
front = preback->next;
preback->next = front->next; //会影响dummyhead 特殊情况下此处dummyhead和preback指向同一个内存块
delete front;
head = dummyhead->next; //如果单链表里面只有一个节点,front和preback指针将一直不动,删除front将导致head内存被删除。考虑特殊情况,用dummy->next充值head.(preback和dummyhead指向相同的内存块,特例时,preback->next在line40赋值为null,使得dummyhead->next也被赋为null)
//一个节点时,返回null.
delete dummyhead;
return head;
}
};
思路:错误的想要构建一个反向的List,然后删掉第N个节点。--》这样会导致返回的反向list不是原List顺序。或者也可以在求反一次,但是很复杂。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *removeNthFromEnd(ListNode *head, int n) {
//移除从单链表倒数第N个节点,并返回删除后的单链表头
//创建一个反向链表(利用头插法)
ListNode *reversL;
*reversL = (ListNode)malloc(sizeof(Node));
(*reversL)->next = NULL;
ListNode p,q;
p = *head;
while(p->next != NULL)
{
q = (ListNode)malloc(sizeof(Node)); //生成新结点
q->val = p->val;
q->next = (*reversL)->next;
(*reversL)->next = q;
p = p->next;
}
//删除原列表的倒数第N个结点,等价于删除reversL的第N个结点
int j;
p = *reversL;
j = 1;
while(p->next && j < n)
{
p = p->next;
j++;
}
q = p->next;
p->next = q->next;
free(q);
return *reversL;
}
};