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个节点。更简单的问题,让你通过一次遍历找到链表的中间节点,设置两个指针,一个每次移动2个节点,一个每次移动一个节点,当快指针为NULL时,慢指针的位置就是中间节点的位置。怎么找到倒数第n个点呢,还是设两个指针,让一个指针先移动n的节点,然后让另一个指针从头指针开始和它一起移动,当先移动的为NULL时,后移动的就是要被删除的元素,需要保存下它的前一个指针。如果第一个指针移动n个节点之后已经是NULL了,也就是移动了链表长度n次,那么要删除的元素就是第一个节点。
不管是顺数n个还是倒数n个,其实都是距离-标尺问题。标尺是一段距离可以用线段的两个端点来衡量。如果我们用两个指针,并保持他们的距离为n,那么当这个线段的右端指向末尾节点时,左端节点就指向倒数第n个节点。
class Solution {
public:
ListNode *removeNthFromEnd(ListNode *head, int n) {
ListNode *first = head;
ListNode *second = head;
ListNode *del = NULL;
ListNode *presecond = head;
while(NULL != first && n>0)
{
first = first->next;
n --;
}
if(NULL == first)
{
del = head;
head = head->next;
delete del;
return head;
}
while(NULL != first)
{
first = first->next;
presecond = second;
second = second ->next;
}
del = second ;
presecond->next = second->next;
delete del;
return head;
}
};
增加一个表头节点,这样就不用区分要删除的是第一个节点,表头节点的作用就是让删除或者在第一个节点前插入节点易于操作。
class Solution {public:ListNode * removeNthFromEnd ( ListNode * head , int n ) {ListNode new_head ( - 1 );new_head . next = head ;ListNode * front = & new_head , * rear = & new_head ;for ( int i = 0 ; i < n ; i ++ )front = front -> next ;while ( front -> next != NULL ) {front = front -> next ;rear = rear -> next ;}ListNode * tmp = rear -> next ;rear -> next = rear -> next -> next ;delete tmp ;head = new_head . next ;return head ;}};