算法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

posted on 2025-04-07 22:58  sakura430  阅读(20)  评论(0)    收藏  举报