# Solution 1
def removeNthFromEnd(head: Optional[ListNode], n: int) -> Optional[ListNode]:
# first we compute the length of the linked list
curr, list_len = head, 0
while curr:
curr = curr.next
list_len += 1
# to is the (list_len - n - 1) node, ie the node right before the (list_len - n) node, the node to remove
to = list_len - n - 1
# if to is negative, the element to remove is the first one and hence returning head.next will remove it
if to<0:
return(head.next)
# otherwise go to the (list_len - n - 1) node
curr, i = head, 0
for i in range(to):
curr = curr.next
# link the (list_len - n - 1) node to its grandchildren ie its next.next element
curr.next = curr.next.next
return(head)