1.题目内容
给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。
示例 1:
输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]
2.解题思路
这是一个链表删除问题,一般情况从下面几个步骤来看。
1.判断链表是否为空;
2.判断头节点是否是待删除的节点;
3.判断第2步删除完之后链表是否为空。
4.中间位置的连续节点删除,从head开始,定义一个prev引用,使prev一定指向的不是待删除的节点。
以示例1为例,展示解题思路。
2.1虚拟头节点法
为了不单独处理头节点的情况,引入一个虚拟头节点dummyHead,这个节点不存储具体的值,就作为链表的头来使用,所有存储元素的节点一定都有前驱。那么所有的操作就统一了,无论是插入还是删除,都可以看作是中间位置的插入与删除。
本题中先引入一个虚拟头节点dummyHead,定义一个prev引用,使prev指向的一定不是待删除的节点。
要删除值为6的节点,遍历一遍此单链表,当prev.next.val=6时,断掉6的节点和其它节点的连接,使prev指向下一个值不为6的节点。
直到prev.next==null。遍历结束,删除完毕。
2.2递归
递归三要素:
1.大问题能拆分为子问题的解
2.拆分后的子问题和原问题除了数据规模不同,解决思路完全相同
3.存在递归的终止条件(不借助任何外部函数的特殊值,直接得出答案)。
本题是传入一个以head为头节点的链表,就能删除其中所有值为val的节点,返回删除后新的链表的头节点。函数名为removeElements。
1.边界条件:当头节点为空时,返回空;
if(head==null){
return null;
}
2.当头节点不为空时,要删除值为val的节点,调用此函数removeElements,先把以head.next为头节点的自恋表中的所有值为val的节点删除完。
head.next=removeElements(head.next.val);
3.代码展示
3.1虚拟头节点法的代码
public ListNode removeElements(ListNode head, int val) {
//链表是否为空
if(head==null){
return null;
}
ListNode dummyHead=new ListNode();
dummyHead.next=head;
//prev一定指向值不为val的节点
ListNode prev=dummyHead;
while(prev.next!=null){
if(prev.next.val==val){
prev.next=prev.next.next;
}else{
prev=prev.next;
}
}
return dummyHead.next;
}
3.2递归的代码
public ListNode removeElements(ListNode head, int val) {
if(head==null){
return null;
}
head.next=removeElements(head.next,val);
return head.val==val?head.next:head;
}