题目:
给你一个链表的头节点 head
和一个整数 val
,请你删除链表中所有满足 Node.val == val
的节点,并返回 新的头节点 。
输入: head = [1,2,6,3,4,5,6], val = 6
输出: [1,2,3,4,5]
/**
* 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} val
* @return {ListNode}
*/
var removeElements = function(head, val) {
let p = new ListNode(0, head);// 新建一个虚拟头节点
let current = p; //这个指针是用来移动的
//遍历条件是当前指针指向的下一个节点存在
while(current.next){
if(current.next.val === val){
current.next = current.next.next;
continue;
}
current = current.next;
}
return p.next;
};
新手上路,记录几个这题初入手时的小白疑惑:
- 移除会了,但移除的前提是要遍历到节点,所以怎么遍历链表?
- 如果头节点就是移除目标,是不是要单独处理?
如果是用原来的head进行遍历和移除操作,那么如果头节点作为移除目标,就需要单独处理
移除头节点的方式如下:
- 头节点往后移,给下一位当
- 删除原来的头节点(看不同语言是否需要释放)
这里索性定义一个统一的虚拟头节点,使得删除操作统一,都是通过前一个节点的next跳过当前节点指向下一个节点,来删除当前节点
定义一个虚拟头节点:let p = new ListNode(0, head);
这边记录一下细节,涉及比较基础性的东西:
while循环,注意到while循环中的第四行有一个continue语句吗
这个continue是非加不可的
《JavaScript高级程序设计(第四版)》中提到
break 和 continue 语句为执行循环代码提供了更严格的控制手段。
其中, break 语句用于立即退出循环,强制执行循环后的下一条语句。
而 continue 语句也用于立即退出循环,但会再次从循环顶部开始执行。
所以这边的continue是用来隔断循环体中两种不同的判断执行情况的
让两种情况分别在不同轮次的循环体中执行