算法day8 移除链表元素
题目描述

思路一:无虚拟头节点
首先,由于我们是非虚拟头节点解法,我们第一步就应该处理head -> val == val这样的情况,这里我们在设置判断条件时要确保head非空,并且应该采取循环结构,从而应对head更新后依旧val域等于val的情况。处理完head后,我们创建一个临时指针cur,赋值为head,这样我们就可以在不改变head的情况下对链表进行操作。在接下来的while判断语句中,我们要注意的问题是cur -> next要确保其非空,避免对空指针操作,随后判断当前cur->next->val是否满足条件,若满足,我们就使其前驱节点指向它的下一个节点,然后释放掉它即可,否则我们就迭代cur->next,循环结束后返回head即可。
代码如下
ListNode* removeElements(ListNode* head, int val) {
while(head != nullptr && head ->val == val){//这里要判断head的后驱是否为空,避免引用空指针;
//并且这里要采用循环的方式持续性的更新头节点,应对head更新后依旧val域指向val的情况
head = head -> next;
}
ListNode *cur = head;
while(cur!=nullptr&&cur->next!=nullptr){
if(cur ->next -> val == val ){
ListNode *s = cur->next;
cur ->next = cur->next->next;
delete s;
}else{
cur = cur->next;
}
}
return head;
}
思路一时间复杂度:O(n)
思路一空间复杂度:O(1)
思路二:虚拟头节点机制
在思路一中,我们使用了while循环来单独处理头节点的删除逻辑,但是在思路二中,我们创建一个虚拟的头节点dummyhead,这个节点永远指向当前链表的头节点(注意,是真正意义上的头节点,而非是固定死的head指针),这样我们就实现了整个链表节点删除逻辑的统一,最后只需要返回dummyhead-->next即可。
代码如下
//这里的思想就是利用哑节点来作为虚拟头节点
ListNode* removeElements(ListNode* head, int val) {
ListNode *dummyhead = new ListNode;
dummyhead -> next = head;
ListNode *cur = dummyhead;
while( cur -> next != nullptr ){
if(cur -> next -> val == val){
ListNode *s = cur -> next;
cur -> next = cur -> next -> next;
delete s;
}else{
cur = cur -> next;
}
}
return dummyhead -> next; //返回值不是head,dummyhead -> next 可以说是实际意义上的头节点,
//head只是一开始用来初始化的,而且其很有可能在循环中已经被释放掉,这样返回会造成访问已释放区域
}
思路二时间复杂度:O(n)
思路二空间复杂度:O(1)
END
浙公网安备 33010602011771号