删除链表的倒数第N个节点
一、LeetCode题解
瞧一瞧~
- 博健的LeetCode题解:Gitbook版本传送门
- 博健的LeetCode题解:CSDN传送门
- 有趣的CSS:Gitbook传送门
- 前端进阶笔记:Gitbook传送门
二、算法题
题目
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
给定的 n 保证是有效的。
进阶:
你能尝试使用一趟扫描实现吗?
解法一(二次遍历操作)
- 时间复杂度:O(n)
- 空间复杂度:O(1)
首先我们将添加一个哑结点
作为辅助,该结点位于列表头部。哑结点用来简化某些极端情况,例如列表中只含有一个结点,或需要删除列表的头部。
- 在第一次遍历中,我们找出列表的长度 L。
- 然后设置一个指向哑结点的指针,并移动它遍历列表,直至它到达第 (L - n) 个结点。
- 把第 (L - n) 个结点的 next 指针重新链接至第 (L - n + 2)个结点。
代码
var removeNthFromEnd = function(head, n) {
var current = head
var len = 0
while (current) {
len++
current = current.next
}
len = len - n
head = { val: '', next: head }
current = head
while (len != 0) {
current = current.next
len--
}
current.next = current.next.next
return head.next
}
结果
解法二(快慢指针)
- 快指针先跑到第n节点。
- 之后,慢指针从头节点,与快指针同时走。
- 快指针走到尾部,慢指针指向了倒数第n个节点
代码
var removeNthFromEnd = function(head, n) {
var current = { val: '', next: head }
var fast = current
var slow = current
for (let i = 1; i <= n + 1; i++) {
fast = fast.next;
}
while (fast != null) {
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return current.next;
}