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 < 0) {
return null;
}
if (1 == total && n == 1) {
return null;
}
if (indexToRemove == 1) {
return head.next;
}
current = head;
ListNode prev = null;
for (int i = 0; i < indexToRemove - 1; i++) {
prev = current;
current = current.next;
}
// i > 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?