2 Different Python Solutions with Explanation
Solution 1: Two Passes\nThe reason why this problem is a medium and not an easy one is because we need to remove the nth node from the end. To do this, we need 
# Solution 1: Two Passes\nThe reason why this problem is a medium and not an easy one is because we need to remove the nth node **from the end**. To do this, we need to find the length of the linked list. That is why we need 2 passes: one to find the length of the linked list and another to actually remove the node.\n\nWe first set `i` as the head and iterate the entire list, with each iteration adding 1 to the length. That is really basic.\n\nNow that we have our length, we can remove the node. To remove a node, you set the previous node\'s link to the node after the one we remove. \n\nSay we want to remove node 2: we set 1\'s next link to 3 instead of 2. Therefore the linked list becomes 0, 1, 3.\n```txt\n 0------->1------->2------->3\n 0        1        2        3\n|_|----->|_|-------------->|_|\n```\n\nAlso, the corner case is that `n` is the length, in which we don\'t do anything but return the node after `head`.\n\nNow onto removing the node:\nWe move our `j` pointer to the node **before** the node we want to remove. To do that, we need to mvoe it `length-n-1` times. \n\nOnce we are at that desired node, we just set `j`\'s next pointer to the node after the node we want to remove. \n\nFor those of you who are worried about memory leaks: python has a garbage collection system that\'s automated, so you don\'t have to take care of that.\n```py\n# Definition for singly-linked list.\n# class ListNode(object):\n#     def __init__(self, val=0, next=None):\n#         self.val = val\n#         self.next = next\nclass Solution(object):\n    def removeNthFromEnd(self, head, n):\n        """\n        :type head: ListNode\n        :type n: int\n        :rtype: ListNode\n        """\n        i = head\n        length = 0\n        while i:\n            i = i.next\n            length += 1\n            \n        if length == n:\n            return head.next\n        j = head\n        for x in range(length-n-1):\n            j = j.next\n        j.next = j.next.next\n        return head\n```\n\n# Solution 2: One Pass\nThis is the optimal solution: we maintain two pointers and are able to do the entire thing (find length and remove node) in **one pass**.\n\nThe trick is that the distance between the 2 pointers is `n`, so when we have the right pointer at the end, the left pointer will be exactly at the node before the node we want to remove. \n\nNote: to prevent the right node from becoming None (go after the last node), I use `while right.next` instead of `while right` as my loop definition\n\nWe first move the right pointer `n` times, so that the distance between the left and right pointers is `n`.\n\nNow we maintain this "window" and move both pointers until the right pointer is at the end of the list. Now, the left pointer is at the node before the node we want to remove, so we can just remove the node. \n\nIf you want to know how to remove a node, I explain it in the first solution (so scroll up). \n```py\n# Definition for singly-linked list.\n# class ListNode(object):\n#     def __init__(self, val=0, next=None):\n#         self.val = val\n#         self.next = next\nclass Solution(object):\n    def removeNthFromEnd(self, head, n):\n        """\n        :type head: ListNode\n        :type n: int\n        :rtype: ListNode\n        """\n        left = right = head\n        for i in range(n):\n            right = right.next\n            \n        if not right:\n            return left.next\n        \n        while right.next:\n            left = left.next\n            right = right.next\n        left.next = left.next.next\n        return head\n```\n\n**If you liked this, please upvote to support me!**
['Linked List', 'Two Pointers', 'Python']