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,就知道这个要删除的节点是正着数的第几个,然后再沿着链表去找到这个节点并删除它。但这样的问题就是如果发现要删除的节点是正着数的最后一个,那么我们要删除它, 实际上要在遍历一遍链表,算法总共就遍历了两次链表(求出链表的长度),这就不符合题目要求,虽然还是可以得到答案。
我们现在做的就是只遍历一次,我们的问题是当我们走到链表末端时,我们知道要倒退几个节点,要解决这个问题,我们可以使用两个指针,第一个指针在前面走,第二个指针在它后面距离它n个位置跟着它走,当第一个指针到达最后一个节点时,第二个指针正好在倒数第n+1个节点,这个时候正好进行删除操作,值得注意的是如果第二个指针正好在倒数第n个节点,那么没法进行删除操作。
另外,如果要删除的是第一个节点,那么需要特殊的处理,即直接更新head指针到head->next,即让它指向第二个节点即可。
代码:
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode p=head, q=head;
for (int i = n; i > 0 ; i--) {
q=q.next;
}
if(q==null){
return head.next;
}
// The head need to be removed, do it.
q=q.next;
while(q!=null){
p=p.next;
q=q.next;
}
p.next=p.next.next; // the one after the p need to be removed
return head;
}