一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第17天,点击查看活动详情。
删除链表中的第N个节点
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
示例 2:
输入:head = [1], n = 1
输出:[]
示例 3:
输入:head = [1,2], n = 1
输出:[1]
提示:
- 链表中结点的数目为 sz
- 1 <= sz <= 30
- 0 <= Node.val <= 100
- 1 <= n <= sz
进阶:你能尝试使用一趟扫描实现吗?
/**
* 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}
*/
var removeNthFromEnd = function(head, n) {
};
非递归解法
- 求出链表的长度
- 长度减去n,得到目标下标
- 循环到目标下标 - 1,拿到目标下标上一个即可
/**
* 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 length = (head) => {
let count = 0;
while(head !== null) {
count++
head = head.next
}
return count
}
var removeNthFromEnd = function(head, n) {
// 求出下标的位置
const last = length(head) - n
if (last === 0) {
// 要删除的是第一个节点
head = head.next
} else {
let current = head
// 获取n的前一个,所以要减1
for (let i = 0; i < last - 1; i++) {
current = current.next
}
current.next = current.next.next
}
return head
};
双指针法
上面是先计算链表的长度,其实不计算链表的长度也是可以,我们可以使用两个指针,一个指针fast先走n步,然后另一个指针slow从头结点开始,找到要删除结点的前一个结点,这样就可以完成结点的删除了。
/**
* 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}
*/
var removeNthFromEnd = function(head, n) {
let fast = head, slow = head;
for (let i = 0; i < n; i++) {
fast = fast.next
}
if (fast === null) {
// 表示删的是头节点
return head.next
}
while(fast.next !== null) {
fast = fast.next
slow = slow.next
}
slow.next = slow.next.next
return head
};