题目描述
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
- 示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:给定的 n 保证是有效的。
单链表定义如下:
/**
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
解法一:
遍历整个链表,获得链表的长度。例如链表为1->2->3->4->5,n=2。当我们遍历遍一遍链表后,长度为5。n=2,所以我们要删除的节点为总长度减去n位置的节点+1,如果要删除节点p,则需要找到其前驱节点q,另q.next = p.next即可。
代码如下:
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode p = head;
int len = 0;
//获取链表的长度
while(p!=null){
len++;
p=p.next;
}
//如果要删除第一个节点
if(n==len)
return head.next;
len = len - n ;
p = head;
//寻找要删除节点的前驱节点
while(len > 1){
p=p.next;
len--;
}
//删除节点
p.next = p.next.next;
return head;
}
解法二:
类似于快慢指针,不同的是不是移动速度的不同,而是初始位置的不同。如果要删除第n个节点,那么指针q从头节点向后移动n个节点的位置,然后p指针从头节点开始,p,q同时向后移动,当q为null时,p恰好在要删除的节点位置。
代码如下:
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode p,q;
p = q = head;
while(n > 0){
q = q.next;
n--;
}
if(q==null){
//如果只有一个节点
if(p.next==null)
return null;
//如果有多个节点,且要删除的节点为第一个
head = head.next;
return head;
}
//找到要删除节点的前驱节点,所以这里为q.next而不是q
while(q.next !=null){
p = p.next;
q = q.next;
}
p.next = p.next.next;
return head;
}
该解法与第一种相比,只需要遍历一遍链表即可。