问题描述
- Given a linked list, remove the n-th node from the end of list and return its head.
- 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. - Follow up:
Could you do this in one pass? - 地址
问题分析
- 该题类似 剑指offer·-链表中倒数第k个结点 ,只不过该题稍微复杂一些,还需要删除该节点。
- 因为涉及到删除倒数第 k 个节点,所以要定位到倒数第 K+1 个节点,并且因为涉及到删除操作,有可能删除掉原链表的头结点,所以必须先设置一个 虚拟
dummy
节点,以便找到删除后的链表头部。 - 方法1 : 先遍历一遍链表,得到链表长度,然后找到第
n - k
个节点,然后删除第n - k + 1
个节点 - 方法2: 双指针:one pass
- 若要定位第 K+1 个节点,那么
fast
和slow
起初指向dummy
节点,然后走k + 1
步,然后slow
和fast
一起走,知道fast
走到末尾,此刻slow
便指向第 K+1 个节点。然后删除即可。
- 若要定位第 K+1 个节点,那么
经验教训
- dummy
- 双指针做法
代码实现
- 方法1:
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode curNode = head;
int length = 0;
while (curNode != null) {
curNode = curNode.next;
++length;
}
curNode = dummy;
int i = 1;
//定位到倒数第 n + 1个节点
while (i < length - n + 1) {
curNode = curNode.next;
++i;
}
curNode.next = curNode.next.next;
return dummy.next;
}
- 双指针
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0);
dummy.next = head;
ListNode fast = dummy;
//快指针先走 n+1 步
for (int i = 1; i <= n + 1; i++) {
fast = fast.next;
}
//快慢指针一起走
ListNode slow = dummy;
while (fast != null) {
slow = slow.next;
fast = fast.next;
}
slow.next = slow.next.next;
return dummy.next;
}