【LeetCode链表#6】移除链表元素
移除链表元素
题目
题意:删除链表中等于给定值 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
输出:[]
初见思路
就操作链表咯
常规思路
如果直接使用头节点作为当前节点的话,在删除头节点时的操作会与删除其他节点时不一致
要统一所有节点的删除方式,需要引入虚拟节点dummy
这样,每当需要删除某个节点时(包括头节点)
都可以遵循:将待删除节点的前一个节点的next指针指向待删除节点的后一个节点 这样一个规则
解题模板
不使用虚拟节点
具体还有两种写法:使用pre、cur指针和只用cur指针
具体看代码:
class Solution {
public ListNode removeElements(ListNode head, int val) {
//删除头节点的情况
while(head != null && head.val == val){
head = head.next;
}
//不要忘了,如果头节点为空就直接退出
if(head == null){
return head;
}
//删除其他节点的情况
//正常情况
ListNode pre = head;
ListNode cur = head.next;
while(cur != null){
if(cur.val == val){
pre.next = cur.next;
}else{
pre = cur;
}
cur = cur.next;
}
// //只使用一个临时节点cur
// //当前节点的指针应该指向head而不是head.next
// //因为如果要删除的就是当前cur指向的值,那么直接指向head的方式就有问题,因为在单向链表中,它找不到待删除节点的上一个节点
// //而第二种方式就避免了这种情况
// ListNode cur = head;
// while(cur != null){
// while(cur.next != null && cur.next.val == val){
// cur.next = cur.next.next;
// }
// cur = cur.next;
// }
return head;//不是返回临时节点cur,要找回最开始的头节点head
}
}
使用虚拟节点
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode removeElements(ListNode head, int val) {
if(head == null){//先判断头节点是否为空,防止操作空指针
return head;
}
//创建一个虚拟节点
ListNode dummy = new ListNode(1, head);
//定义前一个节点pre与当前节点cur
ListNode pre = dummy;
ListNode cur = head;
while(cur != null){//要用循环而不是if,因为删除操作应该是连续的
if(cur.val == val){
pre.next = cur.next;
}else{
pre = cur;
}
cur = cur.next;
}
//注意!要返回虚拟节点的下一个节点,即头节点。而不是直接返回头节点,因为原来的head有可能已经被删了
return dummy.next;
}
}
反正以后就记住使用虚拟节点的方式就行,用的时候也优先这种方式
c++版本
先分析一下给的解题模板
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
}
};
这里需要我们补完一个Solution类,该类中有一个公共的成员函数removeElements
其输入值是ListNode* head(头节点的指针)和一个整形val
代码如下:(没用cur+pre,只定义一个cur)
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
if(head == nullptr){
return head;
}
//创建dummy节点,接在头节点之前
ListNode* dummy = new ListNode(0, head);
ListNode* cur = dummy;
while(cur->next != nullptr){
if(cur->next->val == val){
//处理被删除的节点
ListNode* temp = cur->next;
cur->next = cur->next->next;
delete temp;
}else{
cur = cur->next;
}
}
//这里可以删除定义的dummy,也可以不删,估计是占用内存不同
//head = dummyHead->next;
//delete dummyHead;
//return head;
return dummy->next;
}
};