/// <summary> /// ReverseLinkedListInGroupsOfGivenSizeV2 (Using Stack), TC: O(n*groupsize), SC: O(groupSize) /// This is done via Stack and that's why takes more space. /// https://www.geeksforgeeks.org/reverse-linked-list-groups-given-size-set-2/ /// /// It's previous attempt for better SC is in the file below. /// Method: ReverseLinkedListInGroupsOfGivenSize, TC: O(n*groupsize), SC: O(1) /// https://www.geeksforgeeks.org/reverse-a-list-in-groups-of-given-size/ /// </summary> public void ReverseLinkedListInGroupsOfGivenSizeV2() { var list = LLUtility.CreateSinglyLinkedList(new int[] { 1, 2, 2, 4, 5, 6, 7, 8 }); var head = list.Head; var flag = true; var tempNode = head; var size = 4; var stack = new Stack <ISinglyNode <int> >(); ISinglyNode <int> tempNode2 = null; // iterate while your first moving temp node is valid while (tempNode != null) { // push elements in stack based on group size. for (int i = 0; i < size; i++) { if (tempNode != null) { stack.Push(tempNode); tempNode = tempNode.Next; } // if elements perish before group iteration completes, then come out. else { break; } } // We'll now pull out elements from stack to point to Head to begin // and then iterate through another temp node till we connect all stack // elements in reverse order. Post that, connect reversed list's END // to remaining "initial" list that still needs to be reversed. while (stack.Any()) { // Realign HEAD only once. if (flag) { head = stack.Pop(); tempNode2 = head; flag = false; // Realigned HEAD now should point to the list. list.Head = head; } else { tempNode2.Next = stack.Pop(); tempNode2 = tempNode2.Next; } } // Now, connect reversed list's END // to remaining "initial" list that still needs to be reversed. tempNode2.Next = tempNode; list.Print(); } }
/// <summary> /// ReverseLinkedList, TC: O(n), SC: O(1) /// </summary> public static void ReverseLinkedList() { var list = LLUtility.CreateSinglyLinkedList(new int[] { 1, 2, 3 }.Cast <int>()); list.Print(); // Take 3 elements for this process. ISinglyNode <int> previous, current, next; /* start with previous set to head, current to second element * 0. Iterate till C is not NULL. * 1. We backup NEXT series from C and reverse ties with P and C. * 2. If NEXT series is not null, then shift element by 1, C = Next of C and P = C. * else, SET Next of HEAD of list to NULL and HEAD = C * 3. Set C = Backed up series i.e. N * * INCREASE POINTERS ONE BY ONE */ /* Previous = 1st node, Current = 2nd node */ previous = list.Head; current = list.Head.Next; while (current != null) { /* Save the chain ahead of Current. * Reverse the flow. Current -> Previous * Shift the previous ahead to current now */ next = current.Next; current.Next = previous; previous = current; /* If we reach the end of the list, then we have 1st node (which is the Head of the list) * at the end of the list. Set it's _Next_ as NULL and reset list's Head as current * (which is the current element - so called last element of the original list). */ if (next == null) { list.Head.Next = null; list.Head = current; } // Shift the current ahead to Next (i.e. shift ahead by 1 node) current = next; } Console.WriteLine(); list.Print(); }
/// <summary> /// ReverseLinkedListPostNnodes, TC: O(n), SC: O(1) /// </summary> public static void ReverseLinkedListPostNnodes() { var list = LLUtility.CreateSinglyLinkedList(new int[] { 1, 2, 3, 4, 5, 6 }.Cast <int>()); int counter = 2, index = 0; // reverse after 2 nodes list.Print(); var node = list.Head; ISinglyNode <int> intervalLinkNode = null, previous = null, current = null; // Save the node after which you will reverse your list. // and mark the next two nodes as previous and current // for reversal process while (node != null) { if (index == counter - 1) { intervalLinkNode = node; previous = intervalLinkNode.Next; current = previous.Next; break; } node = node.Next; index++; } ISinglyNode <int> next = null; while (current != null) { next = current.Next; current.Next = previous; if (next == null) { // Reset the interval node's NEXT element to NULL AS END // set the interval's NEXT as the current element which is actually last intervalLinkNode.Next.Next = null; intervalLinkNode.Next = current; break; } previous = current; current = next; } list.Print(); }
/// <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(); }
/// <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(); }