O(N) time O(1) space, Easiest Understanding
The idea is simple, we maintain two pointers, pre, cur in the given List. Pre pointer is always referring to one position before the cur pointer. When we found 
The idea is simple, we maintain two pointers, pre, cur in the given List. Pre pointer is always referring to one position before the cur pointer. When we found pre.val != cur.val && cur.val != cur.next.val, the node referred by cur pointer is a unique node. \n\n\n    public ListNode deleteDuplicates(ListNode head) {\n        if (head == null) {\n            return null;\n        }\n        \n        ListNode dummy = new ListNode(0 == head.val ? 1 : 0); // to guarantee the dummy node is not same as the original head. \n\n        dummy.next = head;\n        \n        ListNode pre = dummy;\n        ListNode cur = head;\n\n        ListNode first = dummy;  // the first node in the new unduplicated(result) list.\n        \n        while (cur != null && cur.next != null) {\n            if (cur.val != pre.val && cur.val != cur.next.val) { // we found a unique node, we connect it at the tail of the unduplicated list, and update the first node.\n                first.next = cur;\n                first = first.next;\n            }\n            pre = cur;\n            cur = cur.next;\n        }\n        \n        if (pre.val != cur.val) { // the last node needs to be dealt with independently\n            first.next = cur;\n            first = first.next;\n        }\n        \n        first.next = null; // the subsequent list is duplicate.\n        \n        return dummy.next;\n    }
[]