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

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

    Use two pointer pTemp and NthNode. Initially, both points to head node of the list. NthNode starts moving only after pTemp made n moves. From the both moves forward until pTemp reaches end of the list. As a result NthNode points to nth node from the end of the linked list.

    public ListNode NthNodeFromEnd(int n){
        ListNode pTemp = head, NthNode = null;
       for(int count=1; count<n;count++){
         if(pTemp!=null){
           pTemp = pTemp.getNext();
         }
       }
       while(pTemp!=null){
         if(NthNode==null){
             NthNode = head;
         }
         else{
            NthNode = NthNode.getNext();
         }
         pTemp = pTemp.getNext();
       }
       if(NthNode!=null){
         NthNode = NthNode.getNext();
         return NthNode;
       }
    return null;
    }
    

    Refer TextBook : "Data Structure and Algorithms Made Easy in Java"

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

    Depending of the memory cost tolerance (O(k) in this solution) we could allocate an array of pointers of length k, and populate it with the nodes as a circular array while traversing the linked list.

    When we finish traversing the linked list, the first element of the array (just be sure to calculate the 0-index properly as it's a circular array) we'll have the answer.

    If the first element of the array is null, there's no solution to our problem.

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

    No you dont know the length of the linkedlist ... You will have to go through once to get length of the likedlist so your approach is little in efficient;

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

    What do you think regarding this approach.

    1. Count length of the linkedlist.
    2. Actual Node index from head = linkedlist length - given index;
    3. Write a function to travesre from head and get the node at the above index.
    0 讨论(0)
  • 2020-12-04 06:44

    First of all

    As mention in comment, but to be more clear, the question is from:

    <Cracking the coding interview 6th> | IX Interview Questions | 2. Linked Lists | Question 2.2.

    It's a great book by Gayle Laakmann McDowell, a software engineer from Google, who has interviewed a lot people.


    Approaches

    (Assuming the linked list doesn't keep track of length), there are 2 approaches in O(n) time, and O(1) space:

    • Find length first, then loop to the (len-k+1) element.
      This solution is not mentioned in the book, as I remember.
    • Loop, via 2 pointer, keep them (k-1) distance.
      This solution is from the book, as the same in the question.

    Code

    Following is the implementation in Java, with unit test, (without using any advanced data structure in JDK itself).

    KthToEnd.java

    /**
     * Find k-th element to end of singly linked list, whose size unknown,
     * <p>1-th is the last, 2-th is the one before last,
     *
     * @author eric
     * @date 1/21/19 4:41 PM
     */
    public class KthToEnd {
        /**
         * Find the k-th to end element, by find length first.
         *
         * @param head
         * @param k
         * @return
         */
        public static Integer kthToEndViaLen(LinkedListNode<Integer> head, int k) {
            int len = head.getCount(); // find length,
    
            if (len < k) return null; // not enough element,
    
            return (Integer) head.getKth(len - k).value; // get target element with its position calculated,
        }
    
        /**
         * Find the k-th to end element, via 2 pinter that has (k-1) distance.
         *
         * @param head
         * @param k
         * @return
         */
        public static Integer kthToEndVia2Pointer(LinkedListNode<Integer> head, int k) {
            LinkedListNode<Integer> p0 = head; // begin at 0-th element,
            LinkedListNode<Integer> p1 = head.getKth(k - 1); // begin at (k-1)-th element,
    
            while (p1.next != null) {
                p0 = p0.next;
                p1 = p1.next;
            }
    
            return p0.value;
        }
    
        static class LinkedListNode<T> {
            private T value;
            private LinkedListNode next;
    
            public LinkedListNode(T value) {
                this.value = value;
            }
    
            /**
             * Append a new node to end.
             *
             * @param value
             * @return new node
             */
            public LinkedListNode append(T value) {
                LinkedListNode end = getEnd();
                end.next = new LinkedListNode(value);
                return end.next;
            }
    
            /**
             * Append a range of number, range [start, end).
             *
             * @param start included,
             * @param end   excluded,
             */
            public void appendRangeNum(Integer start, Integer end) {
                KthToEnd.LinkedListNode last = getEnd();
                for (int i = start; i < end; i++) {
                    last = last.append(i);
                }
            }
    
            /**
             * Get end element of the linked list this node belongs to, time complexity: O(n).
             *
             * @return
             */
            public LinkedListNode getEnd() {
                LinkedListNode end = this;
                while (end != null && end.next != null) {
                    end = end.next;
                }
    
                return end;
            }
    
            /**
             * Count of element, with this as head of linked list.
             *
             * @return
             */
            public int getCount() {
                LinkedListNode end = this;
                int count = 0;
                while (end != null) {
                    count++;
                    end = end.next;
                }
    
                return count;
            }
    
            /**
             * Get k-th element from beginning, k start from 0.
             *
             * @param k
             * @return
             */
            public LinkedListNode getKth(int k) {
                LinkedListNode<T> target = this;
                while (k-- > 0) {
                    target = target.next;
                }
    
                return target;
            }
        }
    }
    

    KthToEndTest.java

    (unit test, using TestNG, or you change to JUnit / .., as wish)

    import org.testng.Assert;
    import org.testng.annotations.BeforeClass;
    import org.testng.annotations.Test;
    
    /**
     * KthToEnd test.
     *
     * @author eric
     * @date 1/21/19 5:20 PM
     */
    public class KthToEndTest {
        private int len = 10;
        private KthToEnd.LinkedListNode<Integer> head;
    
        @BeforeClass
        public void prepare() {
            // prepare linked list with value [0, len-1],
            head = new KthToEnd.LinkedListNode(0);
            head.appendRangeNum(1, len);
        }
    
        @Test
        public void testKthToEndViaLen() {
            // validate
            for (int i = 1; i <= len; i++) {
                Assert.assertEquals(KthToEnd.kthToEndViaLen(head, i).intValue(), len - i);
            }
        }
    
        @Test
        public void testKthToEndVia2Pointer() {
            // validate
            for (int i = 1; i <= len; i++) {
                Assert.assertEquals(KthToEnd.kthToEndVia2Pointer(head, i).intValue(), len - i);
            }
        }
    }
    

    Tips:

    • KthToEnd.LinkedListNode
      It's a simple singly linked list node implemented from scratch, it represents a linked list start from itself.
      It doesn't additionally track head / tail / length, though it has methods to do that.
    0 讨论(0)
  • 2020-12-04 06:45

    You can just loop through the linkedlist and get the size. Once you have the size you can find the n'th term in 2n which is O(n) still.

    public T nthToLast(int n) {
        // return null if linkedlist is empty
        if (head == null) return null;
    
        // declare placeholder where size of linkedlist will be stored
        // we are hoping that size of linkedlist is less than MAX of INT
        int size = 0;
    
        // This is O(n) for sure
        Node i = head;
        while (i.next != null) {
            size += 1;
            i = i.next;
        }
    
        // if user chose something outside the size of the linkedlist return null
        if (size < n)
            return null;
    
        // This is O(n) if n == size
        i = head;
        while(size > n) {
            size--;
            i = i.next;
        }
    
        // Time complexity = n + n = 2n
        // therefore O(n)
    
        return i.value;
    }
    
    0 讨论(0)
提交回复
热议问题