Remove nth node from last position in linked list Description:

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


  Given linked list: 1->2->3->4->5, and n = 2.
  
  After removing the second node from the end, the linked list becomes
  1->2->3->5.


Note:

Given n will always be valid.
Try to do this in one pass.

Code:

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        int total = 0;
        ListNode current = head;
        while (current != null) {
            total++;
            current = current.next;
        }
        // current must be null here

        // 1 based index
        int indexToRemove = total - n + 1;
        if (indexToRemove &lt; 0) {
            return null;
        }
        if (1 == total &amp;&amp; n == 1) {
            return null;
        }
        if (indexToRemove == 1) {
            return head.next;
        }

        current = head;
        ListNode prev = null;
        for (int i = 0; i &lt; indexToRemove - 1; i++) {
            prev = current;
            current = current.next;
        }
        // i &gt; indexToRemove

        if (current == null) { // last
            prev.next = null;
        }
        else {
            prev.next = current.next;   
        }
        return head;
    }
}


Questions:

I managed to run the code and pass all the tests but I still feel confused while dealing with off-by-one errors and NullPointerException. The question felt quite easy at first but implementation took a lot of time because of above two errors and correcting them, it was like I was shooting in the dark.

I still feel I have written a lot of extra code which could have been avoided.

What mental model or basic rules I can learn to visualise or understand program states and avoid such errors?
You failed to solve the "try to do this in one pass" part, as you iterate through the list once to find the total size and a second time to find the nth element from the start.

The algorithmic idea is, to use two pointers into the list:


Initialize poiner1 to head, advance n times (if n is the distance from the tail you seek)
Then, initialize pointer2 to head, advance both pointers, until pointer1 is null, i.e. reached the end of the list.
Now, pointer2 should point to the end-nth element


Removal as usual.