How to find nth element from the end of a singly linked list?
//this is the recursive solution
//initial call
find(HEAD,k);
// main function
void find(struct link *temp,int k)
{
if( temp->next != NULL)
find( temp->next, k);
if((c++) == k) // c is initially declared as 1 and k is the node to find from last.
cout<<temp->num<<' ';
}
The key to this algorithm is to set two pointers p1
and p2
apart by n-1
nodes initially so we want p2
to point to the (n-1)th
node from the start of the list then we move p2
till it reaches the last
node of the list. Once p2
reaches end of the list p1
will be pointing to the nth node from the end of the list.
I've put the explanation inline as comments. Hope it helps:
// Function to return the nth node from the end of a linked list.
// Takes the head pointer to the list and n as input
// Returns the nth node from the end if one exists else returns NULL.
LinkedListNode nthToLast(LinkedListNode head, int n) {
// If list does not exist or if there are no elements in the list,return NULL
if (head == null || n < 1) {
return null;
}
// make pointers p1 and p2 point to the start of the list.
LinkedListNode p1 = head;
LinkedListNode p2 = head;
// The key to this algorithm is to set p1 and p2 apart by n-1 nodes initially
// so we want p2 to point to the (n-1)th node from the start of the list
// then we move p2 till it reaches the last node of the list.
// Once p2 reaches end of the list p1 will be pointing to the nth node
// from the end of the list.
// loop to move p2.
for (int j = 0; j < n - 1; ++j) {
// while moving p2 check if it becomes NULL, that is if it reaches the end
// of the list. That would mean the list has less than n nodes, so its not
// possible to find nth from last, so return NULL.
if (p2 == null) {
return null;
}
// move p2 forward.
p2 = p2.next;
}
// at this point p2 is (n-1) nodes ahead of p1. Now keep moving both forward
// till p2 reaches the last node in the list.
while (p2.next != null) {
p1 = p1.next;
p2 = p2.next;
}
// at this point p2 has reached the last node in the list and p1 will be
// pointing to the nth node from the last..so return it.
return p1;
}
Alternatively we can set p1
and p2
apart by n nodes instead of (n-1)
and then move p2
till the end of the list instead of moving till the last node:
LinkedListNode p1 = head;
LinkedListNode p2 = head;
for (int j = 0; j < n ; ++j) { // make then n nodes apart.
if (p2 == null) {
return null;
}
p2 = p2.next;
}
while (p2 != null) { // move till p2 goes past the end of the list.
p1 = p1.next;
p2 = p2.next;
}
return p1;
Your algorithm works by first creating references to two nodes in your linked list that are N nodes apart. Thus, in your example, if N is 7, then it will set p1 to 8 and p2 to 4.
It will then advance each node reference to the next node in the list until p2 reaches the last element in the list. Again, in your example, this will be when p1 is 5 and p2 is 10. At this point, p1 is referring to the Nth to the last element in the list (by the property that they are N nodes apart).
What do you think regarding this approach.
- Count length of the linkedlist.
- Actual Node index from head = linkedlist length - given index;
- Write a function to travesre from head and get the node at the above index.