import java.util.*;

/*
 * public class ListNode {
 *   int val;
 *   ListNode next = null;
 *   public ListNode(int val) {
 *     this.val = val;
 *   }
 * }
 */

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param head ListNode类 
     * @return ListNode类
     */
    public ListNode deleteDuplicates (ListNode head) {
        // write code here
        //创建一个虚拟头节点用于处理第一个元素重复的情况
        ListNode dummy = new ListNode(1001);
        dummy.next = head;
        ListNode last = dummy;
        ListNode mark = dummy.next;
        if(mark == null) return head;
        ListNode cur = mark.next;
        if(cur == null) return head;
        //判断是否已经有前置元素重复
        Boolean isSame = false;
        while(cur!=null){
            if(mark.val != cur.val){
                if(isSame){
                    isSame = false;
                    last.next = cur;
                    mark = cur;
                    cur = cur.next;

                }
                else {
                    last = mark;
                    cur = cur.next;
                    mark = mark.next;
                }
                
            }
            else {
                cur = cur.next;
                isSame = true;
            }
        }
        //处理最后一个元素是重复的情况,即cur == null,但是mark == cur,没有删除最后一部分重复元素
        if(isSame) {
            isSame = false;
            last.next = cur;
        }
        return dummy.next;
    }
}

链表长度为0,1时,直接返回

需要加一个dummy虚拟头节点,处理链表开头的元素是重复元素的情况。

使用三个指针,mark指向需要比较的元素,cur指向当前的元素,last指向当前比较的元素的前一个元素,方便删除链表。

需要一个标志位isSame区分当cur不等于mark时,是否前面已经有重复的元素。

不断移动last,mark,cur。当mark==cur时,last和mark不动,将标志位isSame设置为true以后,继续移动cur;当cur不等于mark时,

如果标志位isSame是true,说明前面有重复元素,即mark到cur的前一个元素,都是重复的,那么将last指向cur即可删除这些重复元素,将mark设置为cur,cur往后挪一个位置,继续移动三个指针;

如果标志位isSame是false,说明前面的元素都是不重复的,那么直接将三个指针往后挪一个位置即可。

退出循环以后,还需要单独判断isSame是不是true,如果为true,说明链表结尾的元素也是重复元素,需要单独处理。