正题
剑指 Offer 18. 删除链表的节点
给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。
返回删除后的链表的头节点。
注意: 此题对比原题有改动
示例 1:
输入: head = [4,5,1,9], val = 5
输出: [4,1,9]
解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.
示例 2:
输入: head = [4,5,1,9], val = 1
输出: [4,5,9]
解释: 给定你链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9.
解析:
单纯地删除链表中的节点还是比较简单的,具体思路即设置 pre 节点 和 p 节点, pre 节点和 p 节点都是遍历链表所得到的,唯一不同的是,pre 节点要滞后 p 节点一个元素。
为什么要滞后一个元素呢?原因是单向链表是不能回退的,当你找到要删除的节点的时候,需要记录该节点的位置,然后重新遍历,再去用他上一个节点的 next 指针 指向他的下一个节点,用 pre 保存了上一个节点就很方便的可以直接指向 p 的下一个节点达到删除 p 节点的目的了。
代码:
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @param {number} val
* @return {ListNode}
*/
var deleteNode = function(head, val) {
let p = head
let pre = null
while(p) {
if (p.val === val) {
if (!pre) {
head = p.next
} else {
pre.next = p.next
}
return head
}
pre = pre ? pre.next : p
p = p.next
}
};
PS: 有个细节要注意,当要删除的节点是第一个元素时候,我们是没有 pre 指针的,那么只要将 head 指向 head 的 next 就可以了。
使用单指针能否删除节点
答案是可以的,我们只需要以 p 当作是 pre 节点,那么我们要删除的节点为 p.next,我们去判断 p.next.val 是否和 入参 val 相等即可。
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @param {number} val
* @return {ListNode}
*/
var deleteNode = function(head, val) {
let p = head
if (p.val === val) {
head = p.next
return head
}
while(p.next.val !== val) {
p = p.next
}
p.next = p.next.next
return head
};
删除节点的方法还有很多,这里仅仅随意想到2个,记录一下。