Beginner Level To Optimised Solution
1. Beginner Level -\n\nIn this approach, we are using an auxliary space (HashMap and HashSet) to point out duplicates and in the HashSet we are not considering 
**1. Beginner Level -**\n\nIn this approach, we are using an auxliary space (HashMap and HashSet) to point out duplicates and in the HashSet we are not considering those duplicates.\n\nI can certainly tell that it is a very lengthy approach, but in an Interview, it is bit easy to come up with, if you have a good knowledge of HashMap & HashSet.\n\n```\nclass Solution {\n    public ListNode deleteDuplicates(ListNode head) {\n        if(head == null) { return null; }\n        \n        HashMap<Integer, Integer> map = new HashMap<>();\n        ListNode node = head;\n        \n        // Traversing the LL and making the Map such that we can point duplicates\n        while(node != null){\n            if(map.containsKey(node.val)) { map.put(node.val, 1); }\n            else { map.put(node.val, 0); }\n            node = node.next;\n        }\n        \n        HashSet<Integer> finalNodeVals = new HashSet<>();\n        for(int i : map.keySet()){\n            if(map.get(i) == 0) { finalNodeVals.add(i); }\n        }\n        \n        if(finalNodeVals.size() == 0) { return null; }\n        \n        ListNode node1 = head, finalHead = head;\n        boolean first = true;\n        \n        while(node1 != null){\n            if(finalNodeVals.contains(node1.val) && first == true) { \n                head = node1; finalHead = head; first = false; \n            }\n            else if(finalNodeVals.contains(node1.val) && first == false) { \n                head.next = node1; head = head.next;\n            }\n            node1 = node1.next;\n        }\n        \n        head.next = null;\n        \n        return finalHead;\n    }\n}\n```\n\n**Time Complexity = O(n)\nSpace Complexity = O(n)**\n\n**2. Optimised Level :-**\n\nBelow is the algorithm for the problem - \n\n* Make three nodes `pre`, \'ans\' & `curr`.\n* `pre` will be the previous node to the current node and `curr` will be the current node. \'ans\' will point to `pre` at first, and will stay there.\n* While duplicates found in current node(`curr`), then move on to the next node.\n* If we move on, then the `curr` will **NOT** certainly be the next node to the `pre` node.\n* At this point of time `pre`\'s next pointer will point to `curr`\'s next pointer. This way we are linking the non-duplicate nodes togher.\n* Else the `pre`\'s  next pointer will point to `curr`. Also `pre` will move on by 1 node like `curr`.\n* Move forward the curr.\n* After traversing the entire list as `curr`, just return the next pointed node of `ans`, which is our answer.\n\nPlease practise it to get a better point of view.\n\n```\nclass Solution {\n    public ListNode deleteDuplicates(ListNode head) {\n        ListNode pre = new ListNode(0);\n        pre.next = head;\n        ListNode curr = head, ans = pre;\n        \n        while(curr != null){\n            while(curr.next != null && curr.val == curr.next.val){\n                curr = curr.next;\n            }\n            if(pre.next != curr){\n                pre.next = curr.next;\n            }\n            else{\n                pre.next = curr; pre = pre.next;\n            }\n            curr = curr.next;\n        }\n        \n        return ans.next;\n    }\n}\n```\n\n**Time Complexity: O(n)\nSpace Complexity: O(1)**\n\nHappy Coding :)
['Java']