Skip to content
Related Articles

Related Articles

Partition a Linked List into K continuous groups with difference in their sizes at most 1
  • Difficulty Level : Medium
  • Last Updated : 03 May, 2021

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;
}
  
// Fucntion 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;
}


Output:

{{1  2  3  }, {4  5  6  }, {7  8  }}

Time Complexity: O(N)
Auxiliary Space: O(N)

Attention reader! Don’t stop learning now. Get hold of all the important mathematical concepts for competitive programming with the Essential Maths for CP Course at a student-friendly price. To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.




My Personal Notes arrow_drop_up
Recommended Articles
Page :