第一种
首先自己的想法:
由于链表不可以直接得到链表长度,因此需要先遍历一遍,得到链表长度,再通过长度减去n得到需要删除节点的位置:
想法很简单,写出来的代码如下:
public ListNode removeNthFromEnd(ListNode head, int n) {
if (head == null) return head;
if (head.next == null && n == 1) return null;
ListNode cur = head;
int len = 0; //记录链表的长度
while (cur != null){
len++;
cur = cur.next;
}
int a = len - n; //需要删除的节点位置
ListNode dummy = new ListNode(); //使用一个虚拟头节点,为了删除节点更方便
dummy.next = head;
ListNode temp = dummy; //temp找到需要删除节点的前一个节点
while (a > 0){
temp = temp.next;
a--;
}
temp.next = temp.next.next;
return dummy.next;
}
力扣是可以过的,但是这样需要遍历链表2遍,因此可以改进。
第二种
使用一个fast指针和一个slow指针,fast指针比slow先走n+1步。
代码如下:
public ListNode removeNthFromEnd(ListNode head, int n) {
if (head == null) return head;
if (head.next == null && n == 1) return null;
ListNode dummy = new ListNode();
dummy.next = head;
ListNode fast = dummy;
ListNode slow = dummy;
while( n+1 > 0){
fast = fast.next;
n--;
}
while(fast != null){
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return dummy.next;
}
小tips:
涉及到删除链表的节点,最好使用一个dummy节点(虚拟头节点),因为一旦涉及到需要删除head节点,那么就可以找到head节点的前一个结点,也就是使用dummy.next = head.next,使得head结点被删除,否则head结点无法删除。