原题题目:Given a linked list, remove the n-th node from the end of list and return its head.
-
为了只遍历一次就能找到链表的倒数第n个节点,可以定义两个指针。第一个指针从头结点开始遍历向前走n-1步,第二个指针保持不动;从第k步开始,两个节点一起移动,两个指针的距离保持在n-1,当第一个节点到达尾部的同时第二个节点到达了倒数的第n个节点。
-
但上述的想法是为了找到倒数的第n个节点,我们要做的是删除第n个节点,由于链表是单向链表,取不到第二个指针指向节点的前一个节点。那么开始我们可以让第一个指针走n步,这样的话两个指针之间的距离就是n,我们可以通过将第二个指针指向的节点的next指针指向next.next,就可以将倒数的第n-1个节点删除掉。比如我们要删除4,这样将3的next指针指向5。
-
还有两种很重要的状况要分析,当n的大小刚好等于链表的长度,以及大于链表的长度。
while(n > 0){
faster = faster.next;
-- n;
if(n == 0 && faster == null)
return head.next;
else if(faster == null)
return null;
}
我们上面的if条件是为了判断是不是刚刚好倒数第n个节点就是链表的头结点,那么就返回头结点的next节点,因为题目是返回头节点。但如果n还没等于0,faster指针指向的节点就已经是null值,说明n太大了,这样就得返回空。不能不加区分的就返回头结点的next指针。(若有不同的想法,欢迎多批评指正)
附上代码:
public static ListNode deleteNthFromEnd(ListNode head, int n){
if(head == null || n <= 0)
return null;
ListNode faster = head;
while(n > 0){
faster = faster.next;
-- n;
if(n == 0 && faster == null)
return head.next;
else if(faster == null)
return null;
}
ListNode slower = head;
while(faster.next != null){
slower = slower.next;
faster = faster.next;
}
slower.next = slower.next.next;
return head;
}
public static void main(String[] args) {
ListNode head = new ListNode(1);
ListNode a = new ListNode(2);
ListNode b = new ListNode(3);
head.next = a;
a.next = b;
ListNode res = deleteNthFromEnd(head, 3);
while(res != null){
System.out.print(res.val + " ");
res = res.next;
}
}