/********* Program to find the nth Element from the last of the linked list **************/
        /* Given a linked list 10,20,30,40,50,60 3rd elemt from the last is 40. */
        /* Approach 1 with extra space */
        public int FindKthElementFromLastNodeWithExtraSpace()
        {
            int nthElementFromLsat = 3;
            int linkedListLength = 6;

            LinkedList lst = new LinkedList();

            lst.Add(new Node(10));
            lst.Add(new Node(20));
            lst.Add(new Node(30));
            lst.Add(new Node(40));
            lst.Add(new Node(50));
            lst.Add(new Node(60));

            int[] lstValues = new int[6];
            int indx = 0;

            Node current = lst.head;
            while (current != null)
            {
                lstValues[indx] = current.Value;
                indx++;
                current = current.Next;
            }

            return lstValues[linkedListLength - nthElementFromLsat];
        }
        /* Algorithm */
        /*
          1.  pntr1 and pntr2 start out by both pointing to the head node
              pntr2 is then advanced n-1 nodes.  pntr1 is still

         2.  pointing to the head.  After this, we keep advancing
             pntr2 by one node and pntr 1 is also advanced by one node

          3. Once pntr2 is equal to null we know we  have reached
             the last node and pntr1 now points to the nth to last
             node, and we can return our answer as the node that
             pntr1 is pointing to.

         */
        public int FindKthElementFromLastNode()
        {
            LinkedList lst = new LinkedList();

            lst.Add(new Node(10));
            lst.Add(new Node(20));
            lst.Add(new Node(30));
            lst.Add(new Node(40));
            lst.Add(new Node(50));
            lst.Add(new Node(60));

            Node ptr1 = lst.head;
            Node ptr2 = lst.head;

            int n = 3;
            for (int i = 0; i < n - 1; i++)
            {
                ptr2 = ptr2.Next;
            }

            while (ptr2.Next != null)
            {
                ptr1 = ptr1.Next;
                ptr2 = ptr2.Next;
            }

            return ptr1.Value;
        }
        public LinkedList ReverseLinkedList()
        {
            LinkedList lst = new LinkedList();

            lst.Add(new Node(10));
            lst.Add(new Node(20));
            lst.Add(new Node(30));
            lst.Add(new Node(40));
            lst.Add(new Node(50));

            Node prev = null;
            Node current = lst.head;
            Node next = current.Next;

            while (next != null)
            {
                current.Next = prev;
                prev = current;
                current = next;
                next = current.Next;
            }
            current.Next = prev;
            lst.head = current;

            return lst;
        }
        /* Finding the middle element in only one pass */
        /* Have 2 pointers P1 and P2
        * Increment 2nd pointer by 2 hops and 1st pointer by 1 hop
        * If the 2nd pointer can perform 2 hops again repeat the same process till it can
        * When it cant perform 2 hops first pointer will be in the middle of the linked list.
        */
        public int GetMiddleElementInLinkedListWithOnlyOnePass()
        {
            LinkedList lst = new LinkedList();

            lst.Add(new Node(10));
            lst.Add(new Node(20));
            lst.Add(new Node(30));
            lst.Add(new Node(40));
            lst.Add(new Node(50));
            lst.Add(new Node(60));

            Node ptr1 = lst.head;
            Node ptr2 = lst.head;

            while (ptr2.Next != null && ptr2.Next.Next != null)
            {
                ptr2 = ptr2.Next.Next;
                ptr1 = ptr1.Next;
            }

            return ptr1.Value;
        }
        /* Approach1 */
        /* Scan the entire linked list and find the count of the LinkedList
         * Once we get the count divide it by 2. --> CountOfLinkedList/2
         * Iterate the linkedlist till CountOfLinkedList/2 and Pick the last element which is the middle element of the linked list */
        public int GetMiddleElementInLinkedList()
        {
            int middleEmelent = 0;
            int countOfLinkedList = 0;

            LinkedList lst = new LinkedList();

            lst.Add(new Node(10));
            lst.Add(new Node(20));
            lst.Add(new Node(30));
            lst.Add(new Node(40));
            lst.Add(new Node(50));
            lst.Add(new Node(60));

            Node current = lst.head;

            while (current != null)
            {
                countOfLinkedList = countOfLinkedList + 1;
                current = current.Next;
            }

            current = lst.head;
            int indx = 0;
            while (current != null)
            {
                middleEmelent = current.Value;
                indx = indx + 1;
                current = current.Next;
                if (indx >= (countOfLinkedList / 2))
                {
                    break;
                }
            }
            return middleEmelent;
        }
        private LinkedList _ConstructLinkedListWithLoop()
        {
            Node n1 = new Node(10);
            Node n2 = new Node(20);
            Node n3 = new Node(30);
            Node n4 = new Node(40);
            Node n5 = new Node(50);
            Node n6 = new Node(60);

            n1.Next = n2;
            n2.Next = n3;
            n3.Next = n4;
            n4.Next = n5;
            n5.Next = n6;
            n6.Next = n3;

            LinkedList lnkdLst = new LinkedList();
            lnkdLst.head = n1;

            return lnkdLst;
        }