解法1
先遍历一遍计算链表长度,再遍历一遍删除倒数第n个节点
时间复杂度O(n)
但是遍历了两遍链表
解法2
只遍历一遍链表
同样地加上一个虚拟头结点
对应这个链表,要删除的是p,需要找到p前面的一个节点
这时p指向要删除节点的前一个节点,q指向尾节点
然后,将p,q向前挪,使p指向虚拟头结点
由于p到q之间的长度是固定的,所以如果p是虚拟头结点的话,那么q应该是p向后移动n+1次
接下来让p和q同时向前移动,此时p和q之间的距离并不会发生变化
一直到q指向了null,那么p就指向了要删除元素的前一个节点
这样,只遍历了一遍链表,使用两个指针进行辅助
code
public ListNode removeNthFromEnd(ListNode head, int n) {//虚拟头结点ListNode dummyHead = new ListNode(0);dummyHead.next = head;//声明快慢指针ListNode slow = dummyHead;ListNode fast = dummyHead;//快指针先走n+1步for(int i=0;i<n+1;i++)fast = fast.next;//同时向后移动,直到快指针为null,此时慢指针指向待删除元素的前一个节点while(fast!=null){slow = slow.next;fast = fast.next;}//删除节点slow.next = slow.next.next;//返回真实头结点return dummyHead.next;}// time O(n)// space O(1)
