def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
     if l1 is None:
         return l2
     elif l2 is None:
         return l1
     elif l1.val < l2.val:
         l1.next = self.mergeTwoLists(l1.next, l2)
         return l1
     else:
         l2.next = self.mergeTwoLists(l1, l2.next)
         return l2
    def reverseList(self, head: ListNode) -> ListNode:
        if head is None or head.next is None:
            return head

        p = self.reverseList(head.next)
        head.next.next = head
        head.next = None

        return p
    def reverseList(self, head: ListNode) -> ListNode:
        if head is None:
            return None

        prev = cur = ListNode(head.val)
        while head.next:
            prev = ListNode(head.next.val)
            prev.next = cur

            cur = prev
            head = head.next

        return prev
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        dummy = ListNode()
        dummy.next = head

        # use two pointers
        first = dummy
        second = dummy

        for _ in range(n + 1):
            first = first.next

        while first:
            first = first.next
            second = second.next
        second.next = second.next.next
        return dummy.next
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        dummy = ListNode()
        dummy.next = head

        # count size
        size = 0
        node = head
        while node:
            size += 1
            node = node.next

        # find target's prev node and unlink target node
        prev_node = dummy
        for _ in range(size - n):
            prev_node = prev_node.next
        prev_node.next = prev_node.next.next

        return dummy.next