力扣203.移动链表元素

原题链接:力扣203.移动链表元素

一般来说如果需要遍历链表的话都推荐使用虚拟头节点,这样不会影响到原有链表

思路在代码中已给出
主要讲解下

为什么在创建了虚拟头节点virhead时还要再创建一个临时的遍历节点vir

在while循环的else代码块中,如果是使用virhead进行删除操作,那么就会导致全链表为5 ->4 ->3 ->2 ->1变成 4 ->3->2->1,再进行一次循环又变成3->2->1,代表将原链表覆盖
此时只需要使用遍历节点vir,在虚拟头节点virhead指向head后,将virhead赋值给vir,然后使用vir进行遍历和删除操作,这样就不会影响到虚拟头结点virhead
到最后,因为在代码头部new了一个虚拟头节点,所以在代码最后也需要释放结点
故head = virhead->head 最终返回了head

全代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        //创建虚拟头节点并初始化
        ListNode* virhead = new ListNode(0);
        //将虚拟头节点指向链表头节点
        virhead ->next = head;
        //创建遍历节点vir和virhead一起指向head,主要是用于遍历链表
        ListNode* vir = virhead;

        //如果遍历节点vir不为空,且下一个节点不为空
        while(vir != NULL && vir ->next != NULL)
        {
            //如果vir的下一个节点值为题目给定值,则创建临时节点指向vir的下一个节点
            //此时将vir指向下一个节点(该节点值为题目给定值)所指向的下一个节点,方便进行删除操作
            if(vir ->next ->val == val)
            {
                ListNode* tmp = vir ->next;
                vir ->next = vir ->next ->next;
                //要记得释放链所占用的内存空间
                delete tmp;
            }else
            {//如果不为给定值 则遍历节点vir等于 vir指向的下一个结点

                vir = vir ->next;
            }
        }
        //在vir的下一个节点为空时,退出循环,此时将virhead所指向的位置赋值给head,并删除虚拟头节点
        head = virhead ->next;
        delete virhead;
        return head;
    }
};

你可能感兴趣的:(leetcode,链表,算法)