链表基础:除了掌握单链表,双链表,循环链表的基本定义外,要会使用代码定义链表节点。
struct ListNode {
int val; // 节点上存储的元素
ListNode *next; // 指向下一个节点的指针
ListNode(int x) : val(x), next(NULL) {} // 节点的构造函数;同时初始化构造函数
};
思路1:在原来的链表上直接移除元素(即不使用虚拟头指针),可以锻炼代码能力。
注意:头节点因为没有指针指向,所以跟后面节点的移除方式不同。
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
// 删除头结点
while (head != NULL && head->val == val) { // 注意这里不是if;头节点非空且为目标值
ListNode* tmp = head;//经典temp置换
head = head->next;
delete tmp;//注意清除元素
}
// 删除非头结点
ListNode* cur = head;
while (cur != NULL && cur->next!= NULL) {
if (cur->next->val == val) {//找到删除节点的前一位
ListNode* tmp = cur->next;
cur->next = cur->next->next;
delete tmp;
} else {//删除尾节点
cur = cur->next;
}
}
return head;
}
};
思路2:增加虚拟头指针,目的是使链表内所有元素增减操作统一。
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode* dummyHead = new ListNode(0); // 设置一个虚拟头结点
dummyHead->next = head; // 将虚拟头结点指向head,这样方面后面做删除操作
ListNode* cur = dummyHead;
while (cur->next != NULL) {
if(cur->next->val == val) {//删除该节点的话,需要找到该节点的前一个节点
ListNode* tmp = cur->next;
cur->next = cur->next->next;
delete tmp;
} else {//操作尾指针
cur = cur->next;
}
}
head = dummyHead->next;
delete dummyHead;
return head;
}
};
注意1:尾指针不需要置换,直接else;
注意2:头指针head需要重新定义为虚拟头指针的下一位,因为原来的头指针可能被移除。