给你一个链表的头节点 head
和一个整数 val
,请你删除链表中所有满足 Node.val == val
的节点,并返回 新的头节点 。
示例 1:
输入:head = [1,2,6,3,4,5,6], val = 6 输出:[1,2,3,4,5]
示例 2:
输入:head = [], val = 1 输出:[]
示例 3:
输入:head = [7,7,7,7], val = 7 输出:[]
这里以链表1->4->2->4来举例,移除元素4:
删除元素就是让节点的next指针指向下一个节点的下一个结点。因为单链表的特殊性只能指向下一个结点,刚刚删除的是链表中的第二个和第四个结点,那么如果删除的是头结点又该怎么办?
-
直接使用原来的链表进行删除操作
-
设置一个虚拟头结点进行删除操作
第一种:直接使用原来的链表进行移除
移除头结点和移除其他节点的操作是不一样的,因为链表的其他节点都是通过前一个节点来移除当前节点,而头结点没有前一个节点。
所以头结点如何移除呢,其实只要将头结点向后移动一位就可以,这样就从链表中移除了一个头结点。
这样就移除了头结点,是不是发现,在单链表中移除头结点和移除其他结点的操作方法不一样,其实在写代码的时候也会发现,需要单独写一段来处理移除头结点的情况。
其实可以设置一个虚拟头结点,这样原链表的所有节点都可以按照统一的方式删除
来看看如何设置一个虚拟头
这里来给链表添加一个虚拟头结点为新的头结点,此时要移除这个旧头结点元素1。
这样是不是就可以使用和移除链表其他节点的方式统一了呢?
来看一下,如何移除元素1 呢,还是熟悉的方式,然后从内存中删除元素1。
最后呢在题目中,return 头结点的时候,别忘了 return dummyNode->next;, 这才是新的头结点
代码:
-
直接使用原来的链表进行操作:
public ListNode removeElements(ListNode head, int val) {
while(head!=null && head.val==val){
head = head.next;
}
ListNode curr = head;
while(curr!=null){
while(curr.next!=null && curr.next.val == val){
curr.next = curr.next.next;
}
curr = curr.next;
}
return head;
}
-
设置虚拟头结点进行操作:
public ListNode removeElements(ListNode head, int val) {
if (head == null) {
return head;
}
// 因为删除可能涉及到头节点,所以设置dummy节点,统一操作
ListNode dummy = new ListNode(-1, head);
ListNode pre = dummy;
ListNode cur = head;
while (cur != null) {
if (cur.val == val) {
pre.next = cur.next;
} else {
pre = cur;
}
cur = cur.next;
}
return dummy.next;
}