[Python] 2 pointers solution, explained
Idea here is to traverse our linked list and use two pointers:\n\n1. slow is for node just before duplications begins\n2. fast is for the last node of duplicati
Idea here is to traverse our linked list and use two pointers:\n\n1. `slow` is for node just before duplications begins\n2. `fast` is for the last node of duplication group.\n\nNow, we traverse nodes and do the following steps:\n1. while we have `fast.next` and its value is equal to `fast`, it means, than we have one more duplicate, so we move `fast` pointer to the right.\n2. If it happen, that `slow.next` equal to `fast`, it means, that we have only `1` element in group of duplicated elements, that is we do not need to delete it and we move both pointers to right.\n3. If it happen, that `slow.next` is not equal to `fast`, it means, that we need to skip group of duplicated elements: we create new connection: `slow.next = fast.next`, and also we allocate `fast = slow.next`. Note, that now we still have the original property: `slow` points to node before group of duplicated elements and `fast` will be the last element of this group (after `while fast.next and fast.val == fast.next.val:` line)\n\n**Complexity**: time complexity is `O(n)`: we traverse our list at most twice for each of the pointers. Space complexity is `O(1)`: we did not use any additional memory here.\n\n```\nclass Solution:\n    def deleteDuplicates(self, head):\n        dummy = ListNode(-1)\n        dummy.next = head\n        fast, slow = head, dummy\n        while fast:\n            while fast.next and fast.val == fast.next.val:\n                fast = fast.next\n            if slow.next == fast:\n                slow, fast = slow.next, fast.next\n            else:\n                slow.next = fast.next\n                fast = slow.next\n                \n        return dummy.next\n```\n\nIf you have any questions, feel free to ask. If you like solution and explanations, please **Upvote!**
['Two Pointers']