/**
 * struct ListNode {
 *  int val;
 *  struct ListNode *next;
 *  ListNode(int x) : val(x), next(nullptr) {}
 * };
 */
class Solution {
  public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param head ListNode类
     * @param val int整型
     * @return ListNode类
     */
    ListNode* removeElements(ListNode* head, int val) {
        // write code here
        ListNode* dummy = new ListNode(0);
        dummy->next = head;//增加头节点的虚拟前驱节点,这样原链表的所有节点的处理将统一

        ListNode* p = dummy;
        while(true) {
            if(p->next == nullptr) break;//当p是尾节点时,退出while。不用担心尾节点的数据域等于要删除的元素时,这个节点不会被删掉,前一轮操作已经将其删除过了;
            if(p->next->val == val) {//如果p的下一个节点的数据域匹配上了,就会做跳节点的动作(删掉p->next)
                p->next = p->next->next;
            } else {//没有匹配上,就p不断向后移动
                p = p->next;
            }
        }
        delete dummy;//删除dummy新建的空间
        return head;//如果不delete dummy,也可以直接return dummy->next;返回head一样,dummy->next只是给这条链表起了个别名,我们已经对其各个节点检查操作过了,返回哪个名字都可以,只要代表的是这条链表

    }
};