Partition a Linked List into K continuous groups with difference in their sizes at most 1
Given a linked list consisting of N nodes and an integer K, the task is to split the given Linked List into K continuous groups such that the difference between the size of the adjacent groups after splitting is at most 1 and the groups are sorted in descending order of their lengths.
Note: A group with 0 elements can also be formed.
Examples:
Input: 1 → 2 → 3 → 4, K = 5
Output: {{1}, {2}, {3}, {4}, {}}
Explanation: Required splits are {{1 -> NULL}, {2 -> NULL}, {3 -> NULL}, {4 -> NULL}, {NULL}}.Input: LL: 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8, K = 3
Output: {{1, 2, 3}, {4, 5, 6}, {7, 8}}
Approach: The given problem can be solved based on the observation that forming first N % K groups of size (N / K + 1) and the remaining K – (N % K) groups of size N / K satisfies the conditions. Follow the steps below to solve the problem:
- Initialize a vector of the linked list, says ans, that stores the K groups.
- Store the value of N / K and N % K in the variables, say L and R.
- Traverse the given linked list and perform the following steps:
- Store the value of L in a variable say X and the value of head in the variable say currHead and last.
- If the value of R is positive, then update the value of head to head->next.
- Iterate a loop until X is non-zero and perform the following steps:
- If the last node is the same as the head node then move the head node to the next node.
- Otherwise, join the links between the last node and the head node and update the last to head, and move the head node to the next node.
- Push the current Linked List as the currentHead in the vector ans[].
- If the value of K is greater than 0, then push the NULL Linked List in ans and decrement K by 1.
- After completing the above steps, print the elements of all the Linked List stored in the vector ans[].
Below is the implementation of the above approach:
C++
// C++ program for the above approach #include <bits/stdc++.h> using namespace std; // Link List Node struct ListNode { int val; struct ListNode* next; }; // Function to insert a node // into the Linked List void push(ListNode** head_ref, int node_val) { // Allocate a new dynamic node ListNode* new_node = new ListNode(); // Update new_node->val new_node->val = node_val; // Stores the head_ref new_node->next = (*head_ref); // Update (*head_ref) (*head_ref) = new_node; } // Function to split the linked list // in K groups void splitListInParts(ListNode* head, int K) { // Stores the K groups vector<ListNode*> ans; // If head is NULL if (!head) { // Iterate until K is non-zero while (K--) ans.push_back(NULL); } // Stores the length of the // linked list int N = 0; // Stores the head node of the // linked list ListNode* p = head; // Iterate over the linked list while (p) { // Update p p = p->next; // Update N N++; } int len = N / K; int rem = N % K; p = head; // Iterate over the linked list while (K > 0 && p) { // Stores the length // of the current group int x = len; // Stores the current node ListNode* curr_head = p; // Stores the previous node ListNode* last = p; // If rem is greater than 0 if (rem > 0) { // Update p p = p->next; // Decrement rem by 1 rem--; } // Iterate until x is non-zero while (x--) { // If the last is equal to p if (last == p) p = p->next; // Otherwise else { // Join the link between // last and the current // element last->next = p; // Update the last node last = p; // Update p node p = p->next; } } // Assign NULL to last->next last->next = NULL; // Push the current linked // list in ans ans.push_back(curr_head); // Decrement K K--; } // While K greater than 0 while (K > 0) { // Update the value of ans ans.push_back(NULL); // Increment K K--; } // Print the result cout << "{" ; for ( int i = 0; i < ans.size(); i++) { cout << "{" ; while (ans[i]) { // Print the value cout << ans[i]->val << " " ; // Update ans[i] ans[i] = ans[i]->next; } cout << "}" ; if (i != ans.size() - 1) cout << ", " ; } cout << "}" ; } // Driver Code int main() { ListNode* root = NULL; push(&root, 8); push(&root, 7); push(&root, 6); push(&root, 5); push(&root, 4); push(&root, 3); push(&root, 2); push(&root, 1); int K = 3; splitListInParts(root, K); return 0; } |
Java
// Java program for the above approach import java.util.*; class GFG{ // Link List Node static class ListNode { int val; ListNode next; }; // Function to insert a node // into the Linked List static ListNode push(ListNode head_ref, int node_val) { // Allocate a new dynamic node ListNode new_node = new ListNode(); // Update new_node.val new_node.val = node_val; // Stores the head_ref new_node.next = head_ref; // Update head_ref head_ref = new_node; return head_ref; } // Function to split the linked list // in K groups static void splitListInParts(ListNode head, int K) { // Stores the K groups Vector<ListNode> ans = new Vector<ListNode>(); // If head is null if (head == null ) { // Iterate until K is non-zero while (K-- > 0 ) ans.add( null ); } // Stores the length of the // linked list int N = 0 ; // Stores the head node of the // linked list ListNode p = head; // Iterate over the linked list while (p.next != null ) { // Update p p = p.next; // Update N N++; } int len = N / K; int rem = N % K; p = head; // Iterate over the linked list while (K > 0 && p.next != null ) { // Stores the length // of the current group int x = len; // Stores the current node ListNode curr_head = p; // Stores the previous node ListNode last = p; // If rem is greater than 0 if (rem > 0 ) { // Update p p = p.next; // Decrement rem by 1 rem--; } // Iterate until x is non-zero while (x-- > 0 ) { // If the last is equal to p if (last == p) p = p.next; // Otherwise else { // Join the link between // last and the current // element last.next = p; // Update the last node last = p; // Update p node p = p.next; } } // Assign null to last.next last.next = null ; // Push the current linked // list in ans ans.add(curr_head); // Decrement K K--; } // While K greater than 0 while (K > 0 ) { // Update the value of ans ans.add( null ); // Increment K K--; } // Print the result System.out.print( "{" ); for ( int i = 0 ; i < ans.size(); i++) { System.out.print( "{" ); while (ans.get(i) != null ) { // Print the value System.out.print(ans.get(i).val + " " ); // Update ans[i] ans.set(i, ans.get(i).next); } System.out.print( "}" ); if (i != ans.size() - 1 ) System.out.print( ", " ); } System.out.print( "}" ); } // Driver Code public static void main(String[] args) { ListNode root = new ListNode(); root = push(root, 8 ); root = push(root, 7 ); root = push(root, 6 ); root = push(root, 5 ); root = push(root, 4 ); root = push(root, 3 ); root = push(root, 2 ); root = push(root, 1 ); int K = 3 ; splitListInParts(root, K); } } // This code is contributed by shikhasingrajput |
C#
// C# program for the above approach using System; using System.Collections.Generic; public class GFG{ // Link List Node class ListNode { public int val; public ListNode next; }; // Function to insert a node // into the Linked List static ListNode push(ListNode head_ref, int node_val) { // Allocate a new dynamic node ListNode new_node = new ListNode(); // Update new_node.val new_node.val = node_val; // Stores the head_ref new_node.next = head_ref; // Update head_ref head_ref = new_node; return head_ref; } // Function to split the linked list // in K groups static void splitListInParts(ListNode head, int K) { // Stores the K groups List<ListNode> ans = new List<ListNode>(); // If head is null if (head == null ) { // Iterate until K is non-zero while (K-- > 0) ans.Add( null ); } // Stores the length of the // linked list int N = 0; // Stores the head node of the // linked list ListNode p = head; // Iterate over the linked list while (p.next != null ) { // Update p p = p.next; // Update N N++; } int len = N / K; int rem = N % K; p = head; // Iterate over the linked list while (K > 0 && p.next != null ) { // Stores the length // of the current group int x = len; // Stores the current node ListNode curr_head = p; // Stores the previous node ListNode last = p; // If rem is greater than 0 if (rem > 0) { // Update p p = p.next; // Decrement rem by 1 rem--; } // Iterate until x is non-zero while (x-- > 0) { // If the last is equal to p if (last == p) p = p.next; // Otherwise else { // Join the link between // last and the current // element last.next = p; // Update the last node last = p; // Update p node p = p.next; } } // Assign null to last.next last.next = null ; // Push the current linked // list in ans ans.Add(curr_head); // Decrement K K--; } // While K greater than 0 while (K > 0) { // Update the value of ans ans.Add( null ); // Increment K K--; } // Print the result Console.Write( "{" ); for ( int i = 0; i < ans.Count; i++) { Console.Write( "{" ); while (ans[i] != null ) { // Print the value Console.Write(ans[i].val + " " ); // Update ans[i] ans[i] = ans[i].next; } Console.Write( "}" ); if (i != ans.Count - 1) Console.Write( ", " ); } Console.Write( "}" ); } // Driver Code public static void Main(String[] args) { ListNode root = new ListNode(); root = push(root, 8); root = push(root, 7); root = push(root, 6); root = push(root, 5); root = push(root, 4); root = push(root, 3); root = push(root, 2); root = push(root, 1); int K = 3; splitListInParts(root, K); } } // This code contributed by shikhasingrajput |
Javascript
<script> // javascript program for the above approach // Link List Node class ListNode { constructor() { this .val = 0; this .next = null ; } }; // Function to insert a node // into the Linked List function pushIn(head_ref, node_val) { // Allocate a new dynamic node var new_node = new ListNode(); // Update new_node.val new_node.val = node_val; // Stores the head_ref new_node.next = (head_ref); // Update (*head_ref) head_ref = new_node; return head_ref; } // Function to split the linked list // in K groups function splitListInParts(head, K) { // Stores the K groups var ans = []; // If head is null if (!head) { // Iterate until K is non-zero while (K--) ans.push( null ); } // Stores the length of the // linked list var N = 0; // Stores the head node of the // linked list var p = head; // Iterate over the linked list while (p) { // Update p p = p.next; // Update N N++; } var len = parseInt(N / K); var rem = N % K; p = head; // Iterate over the linked list while (K > 0 && p) { // Stores the length // of the current group var x = len; // Stores the current node var curr_head = p; // Stores the previous node var last = p; // If rem is greater than 0 if (rem > 0) { // Update p p = p.next; // Decrement rem by 1 rem--; } // Iterate until x is non-zero while (x--) { // If the last is equal to p if (last == p) p = p.next; // Otherwise else { // Join the link between // last and the current // element last.next = p; // Update the last node last = p; // Update p node p = p.next; } } // Assign null to last.next last.next = null ; // Push the current linked // list in ans ans.push(curr_head); // Decrement K K--; } // While K greater than 0 while (K > 0) { // Update the value of ans ans.push( null ); // Increment K K--; } // Print the result document.write( "{" ); for ( var i = 0; i < ans.length; i++) { document.write( "{" ); while (ans[i]) { // Print the value document.write( ans[i].val + " " ); // Update ans[i] ans[i] = ans[i].next; } document.write( "}" ); if (i != ans.length - 1) document.write( ", " ); } document.write( "}" ); } // Driver Code var root = null ; root = pushIn(root, 8); root = pushIn(root, 7); root = pushIn(root, 6); root = pushIn(root, 5); root = pushIn(root, 4); root = pushIn(root, 3); root = pushIn(root, 2); root = pushIn(root, 1); var K = 3; splitListInParts(root, K); // This code is contributed by rrrtnx. </script> |
{{1 2 3 }, {4 5 6 }, {7 8 }}
Time Complexity: O(N)
Auxiliary Space: O(N)