前言
这道题leetcode 官方给出了三种解答。分别是:
- 两次遍历:第一次遍历计算链表长度,第二次遍历找出待删除节点的前一个节点。没看答案前我就是用这个方法解题的
- 栈:利用后进先出。遍历把每个节点存到栈中,出栈N+1次,找到待删除节点的前一个节点
- 双指针解法:让一个指针先走k步,然后两个指针一起走,当先走的指针走完链表停止,此时后走的指针即指向待删除节点的前一个节点
在这三种解法,第三种无论是空间复杂度还是时间复杂度都是最优的。故我这里就只介绍第三种解法-双指针解法
一、题目描述
详细描述请看leetcode题目描述
描述:给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
示例:
二、解题
本次将用双指针的方法来解题
2.1 思路
- 首先要明确删除某个节点,要找到待删除节点的前一个节点
- 两个指针pre、cur分别指向虚头、头节点。
- cur走n步
- 然后pre、cur再一起走,直到cur指向null
- 此时pre指向待删除节点的前一个节点
2.2 代码
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @param {number} n
* @return {ListNode}
*/
const removeNthFromEnd = function(head, n) {
// 虚拟头节点
const dummy = new ListNode(-1, head)
// pre指针最后指向被删节点的前一个节点, cur指针遍历链表用
let pre = dummy, cur = head
// cur 先走n步
while(n--) {
cur = cur.next
}
// pre、cur同时走,直到cur走到了null, 此时pre走到了待删除节点的前一个节点
while(cur) {
cur = cur.next
pre = pre.next
}
// 删除节点
pre.next = pre.next.next
return dummy.next
}