/// <summary>
        /// ReverseLinkedListInPairs, TC: O(n), SC: O(1)
        /// </summary>
        public static void ReverseLinkedListInPairs()
        {
            var list = LLUtility.CreateSinglyLinkedList(new int[] { 1, 2, 3, 4, 5, 6, 7, 8 }.Cast <int>());

            list.Print();

            int counter = 0;
            ISinglyNode <int> previous, current, next, intervalLinkNode;

            previous = current = next = intervalLinkNode = null;

            // Everytime for reversal take 3 elements
            // first element - previous, 2nd - current
            // till you reverse both of them...save the NEXT of 2nd element in "next"
            previous = list.Head;
            current  = previous.Next;

            while (current != null)
            {
                next          = current.Next;
                previous.Next = next;
                current.Next  = previous;

                if (counter == 0)
                {
                    list.Head = current;
                }
                else
                {
                    // save the interval last node to point to so-called
                    // current node which will become First element in the pair
                    intervalLinkNode.Next = current;
                }

                // shift the interval node to Last of the Pair.
                intervalLinkNode = previous;
                previous         = next;

                // check do we even have new previous element
                // if yes, do we have NEXT of previous to reverse.
                // if no, then break out from the loop.
                current = previous != null && previous.Next != null ? previous.Next : null;
                counter++;
            }

            list.Print();
        }
Exemplo n.º 2
0
        /// <summary>
        /// AddTwoNumbersContainedInLinkedLists
        ///
        /// Question: You are given two non-empty linked lists representing
        /// two non-negative integers. The digits are stored in reverse order
        /// and each of their nodes contain a single digit. Add the two
        /// numbers and return it as a linked list.
        /// You may assume the two numbers do not contain any leading zero, except the number 0 itself.
        ///
        /// LeetCode Question
        /// https://leetcode.com/problems/add-two-numbers/
        /// Type: LinkedList
        /// Difficulty: Medium
        /// </summary>
        public void AddTwoNumbersContainedInLinkedLists()
        {
            var l1 = LLUtility.CreateSinglyLinkedList(new int[] { 2, 4, 3 }).Head;
            var l2 = LLUtility.CreateSinglyLinkedList(new int[] { 5, 6, 4 }).Head;

            // Initialise it with 0 so we don't have to make flags for checking and iteration.
            // We'll just provide the output with next node instead.
            var sum = new SinglyNode <int>(0);

            int temp, q;

            temp = q = 0;
            ISinglyNode <int> sumPointer = sum;

            // checking the pointer with current digits. If both of them are null means numbers are finished.
            while (l1 != null || l2 != null)
            {
                // scan for nullables because numbers may not be of same length. If they aren't,
                // and one number finishes early then just replace it with 0 and don't hamper the addition
                temp = (l1?.Value ?? 0) + (l2?.Value ?? 0) + q;
                q    = temp / 10;                                  // carry

                sumPointer.Next = new SinglyNode <int>(temp % 10); // remainder goes as new node (actually sum of the nums)
                sumPointer      = sumPointer.Next;                 // move it ahead to store the next remainder in the next iteration

                // move the pointer to next digits. Nullable is used since both the numbers may not be of same length.
                l1 = l1?.Next;
                l2 = l2?.Next;
            }

            // accomodate quotient/carry if it spills over. E.g. 11 > 1  1
            if (q > 0)
            {
                sumPointer.Next = new SinglyNode <int>(q);
            }

            //Return or Print the sum now..
            var list = new SinglyLinkedList <int>();

            list.Head = sum.Next;
            list.Print();
        }
        /// <summary>
        /// FindMiddleElement, TC: O(n), SC: O(1)
        /// </summary>
        public static void FindMiddleElement()
        {
            var linkedList = LLUtility.CreateSinglyLinkedList(new int[] { 1, 2, 3, 4, 5, 6, 7 }.Cast <int>());

            // look for middle element now
            var node = linkedList.Head;
            ISinglyNode <int> middleNode = null;
            var flag = true;

            while (node != null)
            {
                if (flag)
                {
                    middleNode = middleNode == null ? linkedList.Head : middleNode.Next;
                }

                flag = !flag;
                node = node.Next;
            }

            Console.WriteLine(middleNode.Value);
        }
        /// <summary>
        /// RotateLinkedList, TC: O(n), SC: O(1)
        /// </summary>
        public static void RotateLinkedList()
        {
            var list = LLUtility.CreateSinglyLinkedList(new int[] { 1, 2, 3, 4, 5, 6, 7, 8 }.Cast <int>());

            Console.WriteLine("Original Linked List");
            list.Print();
            int toBeRotated = 3, counter = 0;

            Console.WriteLine($"Rotation count: {toBeRotated}\n");

            ISinglyNode <int> newLastNode = null, node = list.Head;

            // Iterate till we reach last node
            while (node.Next != null)
            {
                // Save the node which is to be made LAST
                if (counter == toBeRotated - 1)
                {
                    newLastNode = node;
                }

                node = node.Next;
                counter++;
            }

            // Last node is the new linking node.
            var linkingNode = node;

            // 1. Link the last node to old HEAD now.
            // 2. Reset the HEAD to new node.
            // 3. Set NEW LAST NODE's next to NULL
            linkingNode.Next = list.Head;
            list.Head        = newLastNode.Next;
            newLastNode.Next = null;

            list.Print();
        }
        /// <summary>
        /// ReverseLinkedListInGroupsOfGivenSize, TC: O(n*groupsize), SC: O(1)
        /// https://www.geeksforgeeks.org/reverse-a-list-in-groups-of-given-size/
        /// </summary>
        public static void ReverseLinkedListInGroupsOfGivenSize()
        {
            var list = LLUtility.CreateSinglyLinkedList(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }.Cast <int>());

            list.Print();

            // counter for iteration tracking. Groupsize as given!
            int groupSize = 4, counter;

            // Keep 5 variables. For reversal, usual concept of 3 vars: previous, current and next.
            //
            // intervalLinkNode is for keeping it the first node (which will become last of the group)
            // and will point to (LAST element of the upcoming group - which will become FIRST of that upcoming group)
            //
            // changerNode is for shifting the intervalLinkNode to "NEW" Last node of the reversed group
            // to point to (LAST element of the upcoming group - which will become FIRST of that upcoming group)
            ISinglyNode <int> previous, current, next, intervalLinkNode, changerNode;

            previous = current = next = intervalLinkNode = changerNode = null;

            // this is just to RESET the Head to last element of the first group.
            // After it is false, it will be useless.
            var flag = true;

            // Everytime for reversal take 3 elements. Previous as 1st element, Current as 2nd element
            previous = list.Head;
            current  = previous.Next;

            while (current != null)
            {
                counter = 1;

                /* On start, we have interval node as NULL but in next iterations we will have it as
                 * FIRST node of the group which will become LAST after reversal. This will then point
                 * to FIRST node of the upcoming group (which will actually be the LAST element of the
                 * upcoming group before reversal)
                 */
                if (intervalLinkNode != null)
                {
                    intervalLinkNode.Next = previous;
                }

                // Taking this to shift the intervalLinkNode as to Last node of the group.
                // Just for shifting after each iteration.
                changerNode = previous;

                // Iterate till entire group is reversed and you have no more left. i.e. multiple of group size
                // OR you have an incomplete group at the end, so we will break from the loop.
                while (current != null && counter < groupSize)
                {
                    /* Save the chain ahead of Current.
                     * Reverse the flow. Current -> Previous
                     * Shift the previous ahead to current now
                     */
                    next         = current.Next;
                    current.Next = previous;

                    // shift counters by one node
                    previous = current;
                    current  = next;
                    counter++;
                }

                if (flag)
                {
                    /* set the intervalnode to Head because this will point to new node now
                     * as it has become last element of the first group.
                     * Set Head to the last element of the first group (this is now first element)
                     *
                     * Disable flag.
                     */
                    intervalLinkNode = list.Head;
                    list.Head        = previous;
                    flag             = !flag;
                }
                else
                {
                    /* Connect the intervalNode (which is of the last group) to New _reversed_ first
                     * node of current group.
                     * Shift the interval node to First element (previous) of the current group
                     * which has now become the last element after reversal.
                     */
                    intervalLinkNode.Next = previous;
                    intervalLinkNode      = changerNode;
                }


                // shift counters to first element of next node
                // just like we started inside the inner while loop
                previous = current;

                /* reached the end of the list? then set the intervalNode Next to null
                 * mark the end of the list. Come out now!
                 */
                if (current == null)
                {
                    intervalLinkNode.Next = null;
                    break;
                }

                /* If we have completed the group reversal (no of elements are multiple of group size).
                 * Then link the interval node to first element of reversed group. and it will
                 * automatically come out since current has become NULL.
                 */
                current = previous.Next;
                if (current == null)
                {
                    intervalLinkNode.Next = previous;
                }
            }

            list.Print();
        }