首先需要一个哨兵头节点dummy来避免开始一个节点的分类讨论,导致代码可读性下降的问题

然后我们需要三个指针来判断,post表示前一个,cur表示现在,pre表示下一个
post表示确定没有重复的节点,cur和pre用来探查可能存在重复的区域

如果cur和pre的值不等,则整体往后移动

如果相等,则需要探测相等区域,这个时候pre一直往后移动,cur保持不变

如果cur的值不等于pre了,则有post的下一跳为pre,然后梳理一下post,cur,pre

如果是pre先为nullptr了,则post的吓一跳为nullptr,结束循环,整体就是这个思路,一遍就可以通过

/**
 * struct ListNode {
 *    int val;
 *    struct ListNode *next;
 * };
 */

class Solution {
public:
    /**
     * 
     * @param head ListNode类 
     * @return ListNode类
     */
    ListNode* deleteDuplicates(ListNode* head) {
        // write code here
        //设置哨兵节点
        ListNode* dummy = new ListNode(0);
        dummy->next = head;
        if (head == nullptr || head->next == nullptr) return head;
        ListNode* pre = head->next, * cur = head, * post = dummy;
        while (pre) {
            if (pre->val == cur->val) {
                //延长删除环节
                while (pre != nullptr && pre->val == cur->val) {
                    pre = pre->next;
                }
                if (pre == nullptr) {
                    post->next = nullptr;
                    break;
                } else {
                    post->next = pre;
                    cur = pre;
                    pre = pre->next;
                }
            } else {
                post = cur;
                cur = pre;
                pre = pre->next;
            }
        }
        cur->next = nullptr;
        return dummy->next;
    }
};