19. Remove Nth Node From End of List

19. Remove Nth Node From End of List

  • TABLE OF CONTENTS

    Problem Statement

    Thought Process

    Approach

  • Solution

  • Complexity

  • Conclusion

Hello, Welcome to my Day 1 of Problem Solving and finding solutions to Leetcode's Data Structures and Algorithm questions. Here, I choose a question daily and try to solve it, and finally pen down my process of flow in solving the question.

I hope you find it helpful. Today I will be solving Leetcode's question 19 - Remove Nth Node From End of List.


Problem Statement

  • Given the head of a linked list, remove the n<sup>th</sup> node from the end of the list and return its head.

Example 1

Input: head = [1,2,3,4,5], n = 2
Output: [1,2,3,5]

Example 2

Input: head = [1], n = 1
Output: []

Example

Input: head = [1,2], n = 1
Output: [1]

Thought Process

One approach I had on solving this question was to traverse the linked list to determine its length, subtract 'n' from its length to find the node to be removed from the start of the LinkedList, then traverse the linked list again to remove the node. However, this approach requires two passes through the linked list and has a time complexity of 0(2n) or 0(n).

Two-Pointer Techniques

A more efficient approach is to use the two-pointer technique. We can maintain two pointers left and right and initialize them to point to the head of the linked list. First, we move the right pointer n nodes forward in the linked list. If the right pointer reaches the end of the linked list, the node to be removed is the head node. Otherwise, we move both pointers left and right forward until the right pointer reaches the end of the linked list. At this point, the left pointer is pointing to the node before the node to be removed, and we can remove the nth node by updating the next pointer of the left node to point to the node after the node to be removed.

This approach only requires one pass through the linked list and has a time complexity of O(n) and a space complexity of O(1), where n is the length of the linked list.

The Approach

  • Here is my approach in solving the problem using a two-pointer technique

  • Initialize two pointers left and right to point to the head of the linked list.

  • Move the right pointer n nodes forward in the linked list. If the right pointer reaches the end of the linked list, the node to be removed is the head node. In this case, remove the head node and return the next node.

  • Otherwise, move both pointers left and right forward until the right pointer reaches the end of the linked list. At this point, the left pointer is pointing to the node before the node to be removed.

  • Remove the nth node by updating the next pointer of the left node to point to the node after the node to be removed.

  • Return the head of the updated linked list.

The code Snippet





class Solution:
    def removeNthFromEnd(self, head:ListNode, n:int) -> ListNode:
        dummy = ListNode(0, head)
        left = dummy 
        right = head

        while n > 0 and right:
            right = right.next
            n -= 1

        while right:
            left = left.next
            right = right.next

        #delete
        left.next = left.next.next
        return dummy.next

Explanation of the code

# line 5-7 This line defines a class Solution with a method removeNthFromEnd that takes in two arguments: a head node of a linked list and an integer n representing the node to be removed from the end of the linked list. This method returns the head of the updated linked list after the node is removed.

# Line 7-9 - 
# These lines initialize a dummy node with a value of 0 and set its next pointer to the head node. This dummy node is used to handle the case where the head node needs to be removed. Then, two pointers, left and right, are initialized with left pointing to the dummy node and right pointing to the head node.

# Line 11-13 - This loop moves the right pointer n nodes forward while n is greater than 0 and right is not None. This places the right pointer at the (n+1)th node from the end of the linked list.

#line 15-17 - This loop moves both the left and right pointers forward until the right pointer reaches the end of the linked list. This leaves the left pointer at the (n+1)th node from the end of the linked list.

#line 20-21 - This line sets the left pointer's next pointer to the node after the node to be removed. This removes the node from the linked list.

# This line removes the nth node by updating the next pointer of the left node to point to the node after the node to be removed. Finally, the method returns the head of the updated linked list, which is the next node of the dummy node.

Complexity

Time Complexity:

  • The solution only traverses the linked list once, which takes O(n) time, where n is the length of the linked list.

  • In addition, we perform constant time operations such as pointer updates and arithmetic operations.

  • Therefore, the time complexity of the solution is O(n).

Space Complexity:

  • The solution only uses three pointers: head, left, and right, and a constant number of integer variables.

  • Therefore, the space complexity of the solution is O(1), which is constant space.

Conclusion

In conclusion, the problem of removing the Nth node from the end of a linked list can be efficiently solved using the two-pointer technique. By using two pointers, we can avoid the need to traverse the linked list twice, which would result in a higher time complexity. Instead, we can traverse the linked list once and determine the node to be removed by maintaining a fixed distance between the two pointers.

The solution also highlights the importance of careful pointer manipulation when working with linked lists. By using a dummy node to simplify edge cases, and by updating the next pointer of the left node to remove the nth node, we can effectively remove the node from the linked list while preserving the overall structure of the list.