How to find nth element from the end of a singly linked list?

后端 未结 28 1081
感动是毒
感动是毒 2020-12-04 06:08

The following function is trying to find the nth to last element of a singly linked list.

For example:

If the elements are

相关标签:
28条回答
  • 2020-12-04 06:45

    my approach, what i think is simple and has time complexity O(n).

    Step 1: First get the count of number of nodes. Run a for loop starting from first node to the last node

    Step 2: Once you have the count, apply simple math, for example if we have find 7th node to the last node and the count of all nodes is 12, then (count - index)- 1 will give some kth node, upto which you will have to traverse and it will be the nth node to the last node. In this case (12 -7)-1 = 4

    If the elements are 8->10->5->7->2->1->5->4->10->10 then the result is 7th to last node is 7, which is nothing but 4th node from the beginning.

    0 讨论(0)
  • 2020-12-04 06:45

    Nobody here noticed that Jonathan's version will throw a NullPinterException if the n is larger that the length of LinkedList. Here is my version:

    public Node nth(int n){
            if(head == null || n < 1) return null;
    
            Node n1 = head;
            Node n2 = head;
            for(int i = 1; i < n; i++){
                if(n1.next == null) return null; 
                n1 = n1.next;
            }
    
            while (n1.next != null){
                n1 = n1.next;
                n2 = n2.next;
            }
            return n2;
    }
    

    I just make little change here: when node n1 step forward, instead of checking if n1 is null, I check weather n1.next is null, or else in while loop n1.next will throw a NullPinterException.

    0 讨论(0)
  • 2020-12-04 06:47
    //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<<' ';
    }
    
    0 讨论(0)
  • 2020-12-04 06:47

    There are lots of answers here already, but they all walk the list twice (either sequentially or in parallel) or use a lot of extra storage.

    You can do this while walking the list just once (plus a little bit) using constant extra space:

    Node *getNthFromEnd(Node *list, int n) {
    
        if (list == null || n<1) {
            return null; //no such element
        }
    
        Node *mark1 = list, *mark2 = list, *markend = list;
        int pos1 = 0, pos2 = 0, posend = 0;
    
        while (markend!=null) {
            if ((posend-pos2)>=(n-1)) {
                mark1=mark2;
                pos1=pos2;
                mark2=markend;
                pos2=posend;
            }
            markend=markend->next;
            ++posend;
        }
        if (posend<n) {
            return null; //not enough elements in the list
        }
    
        //mark1 and mark2 are n-1 elements apart, and the end is at least
        //1 element after mark2, so mark1 is at least n elements from the end
    
        while((posend - pos1) > n) {
          mark1 = mark1->next;
          ++pos1;
        }
        return mark1;
    }
    

    This version uses 2 extra pointers does less than N+n traversals, where N is the length of the list and n is the argument.

    If you use M extra pointers, you can get that down to N+ceil(n/(M-1)) (and you should store them in a circular buffer)

    0 讨论(0)
提交回复
热议问题