LeetCode – Remove Nth Node From End of List (Java)

Given a linked list, remove the nth node from the end of list and return its head.

For example, given linked list 1->2->3->4->5 and n = 2, the result is 1->2->3->5.

Java Solution 1 – Naive Two Passes

Calculate the length first, and then remove the nth from the beginning.

public ListNode removeNthFromEnd(ListNode head, int n) {
    if(head == null)
        return null;
 
    //get length of list
    ListNode p = head;
    int len = 0;
    while(p != null){
        len++;
        p = p.next;
    }
 
    //if remove first node
    int fromStart = len-n+1;
    if(fromStart==1)
        return head.next;
 
    //remove non-first node    
    p = head;
    int i=0;
    while(p!=null){
        i++;
        if(i==fromStart-1){
            p.next = p.next.next;
        }
        p=p.next;
    }
 
    return head;
}

Java Solution 2 – One Pass

Use fast and slow pointers. The fast pointer is n steps ahead of the slow pointer. When the fast reaches the end, the slow pointer points at the previous element of the target element.

public ListNode removeNthFromEnd(ListNode head, int n) {
    if(head == null)
        return null;
 
    ListNode fast = head;
    ListNode slow = head;
 
    for(int i=0; i<n; i++){
        fast = fast.next;
    }
 
    //if remove the first node
    if(fast == null){
        head = head.next;
        return head;
    }
 
    while(fast.next != null){
        fast = fast.next;
        slow = slow.next;
    }
 
    slow.next = slow.next.next;
 
    return head;
}

8 thoughts on “LeetCode – Remove Nth Node From End of List (Java)”

  1. =Use fast and slow pointers.

    i would not call fast/slow, they have both same speed. just have distance between.


  2. Covers some more cases:

    Node removeNthFromLast(Node root, int n)
    {
    Node f = root; /* f for forward */
    for (int i = 1 ; i < n && f != null ; i++, f = f.next);

    if (f == null) return root; /* nth not exists - can also throw exception */

    Node helper = new Node(0);
    helper.next = root;

    Node b = helper; /* b for backward */

    /* Distance between b and f is n. */

    for ( ; f.next != null ; f = f.next, b = b.next);

    b.next = b.next.next; /* The actual deletion */

    return helper.next;
    }

    Execution example:

    1->2->3, 2

    n 2
    f 1 2
    i 1 2

    helper 0

    b 0 1
    f 2 3
    f.next null

    0->1->3

    res: 1->3

  3. For the solution 1.
    I think calculating length can be improved like below.

    ListNode fast = head;
    int len = 0;
    while(fast!=null) {
    if(fast.next==null) {
    len++;
    break;
    }

    len += 2;
    fast = fast.next.next;
    }

  4. In solution 2,

    //if remove the first node
    if(fast == null){
    head = head.next;
    return head;
    }

    fast can be null, in cases where N is more than then length of list. Why remove first element in this case?

  5. Treat it like a circle, but I think two pointers is better.
    /**
    * Definition for singly-linked list.
    * public class ListNode {
    * int val;
    * ListNode next;
    * ListNode(int x) { val = x; }
    * }
    */
    public class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
    if (head == null) return head;
    ListNode p = head;
    int len = 0;
    while (p != null) {
    len++;
    if (p.next != null) {
    p = p.next;
    } else {
    break;
    }
    }
    // delete head case
    if (n == len) return head.next;
    ListNode end = p;
    p.next = head;
    int k = len – n;
    while (k > 0) {
    k–;
    p = p.next;
    }
    end.next = null;
    // delete tail case
    if (n == 1) {
    p.next = null;
    } else {
    p.next = p.next.next;
    }
    return head;
    }
    }

  6. we have to check for null in the for loop. Otherwise it’s going to give us NullPointerException

Leave a Comment