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

后端 未结 28 1079
感动是毒
感动是毒 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:21

    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).

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

    Recursive solution:

    Node findKth (Node head, int count, int k) {
        if(head == null)
            return head;
        else {
            Node n =findKth(head.next,count,k);
            count++;
    
            if(count == k)
                return head;
    
            return n;
        }
    }
    
    0 讨论(0)
  • 2020-12-04 06:25

    I think there is one flaw in the question code, and I wonder if its been taken from a book how is this possible... it may execute correctly but code is somewhat logically incorrect. Inside the for loop... the if condition should be checked against p2->next ! = NULL

     for (int j = 0; j < n - 1; ++j) { // skip n-1 steps ahead
           if (p2->next == null) {
           return null; // not found since list size < n
       }
    

    ...rest is fine and explanation as given already the code shifts p2 (n-1) positions advance to p1, then in while loop it move them simultaneously till p2->next reaches the end .. fell free to tell if you find my answer incorrect

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

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

    We take here two pointers pNode and qNode, both initial points to head qNode. Then, traverse till the end of list and the pNode will only traverse when there's a difference between the count and position is greater than 0 and pthNode increments once in each loop.

    static ListNode nthNode(int pos){
    ListNode pNode=head;
    ListNode qNode=head;
    int count =0;
    while(qNode!=null){
        count++;
        if(count - pos > 0)
            pNode=pNode.next;
        qNode=qNode.next;
    }
    return pNode;
    }
    
    0 讨论(0)
  • 2020-12-04 06:27

    Just reverse the linked list in linear time and find the kth element. It still run in linear time.

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