Skip to content
geeksforgeeks
  • Tutorials
    • Python
    • Java
    • Data Structures & Algorithms
    • ML & Data Science
    • Interview Corner
    • Programming Languages
    • Web Development
    • CS Subjects
    • DevOps And Linux
    • School Learning
    • Practice Coding Problems
  • Courses
    • DSA to Development
    • Get IBM Certification
    • Newly Launched!
      • Master Django Framework
      • Become AWS Certified
    • For Working Professionals
      • Interview 101: DSA & System Design
      • Data Science Training Program
      • JAVA Backend Development (Live)
      • DevOps Engineering (LIVE)
      • Data Structures & Algorithms in Python
    • For Students
      • Placement Preparation Course
      • Data Science (Live)
      • Data Structure & Algorithm-Self Paced (C++/JAVA)
      • Master Competitive Programming (Live)
      • Full Stack Development with React & Node JS (Live)
    • Full Stack Development
    • Data Science Program
    • All Courses
  • DSA
  • Practice Sorting
  • MCQs on Sorting
  • Tutorial on Sorting
  • Bubble Sort
  • Quick Sort
  • Merge Sort
  • Insertion Sort
  • Selection Sort
  • Heap Sort
  • Sorting Complexities
  • Radix Sort
  • ShellSort
  • Counting Sort
  • Bucket Sort
  • TimSort
  • Bitonic Sort
  • Uses of Sorting Algorithm
Open In App
Next Article:
Group Balls by Sequence
Next article icon

Group Balls by Sequence

Last Updated : 19 Jun, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report
Try it on GfG Practice
redirect icon

Given an integer array arr[], where each element represents the number written on a ball, and an integer k, determine whether it's possible to rearrange all the balls into groups of size k such that each group contains k consecutive numbers.

Examples:

Input: arr[] = [10, 1, 2, 11], k = 2
Output: true
Explanation: The hand can be rearranged as [1, 2], [10, 11]. There are two groups of size 2. Each group has 2 consecutive cards.

Input: arr[] = [1, 2, 3, 4, 5], k = 2
Output: false
Explanation: The hand cannot be rearranged into groups of 2, since there are 5 cards, and 5 cards cannot be divided into groups of 2.

Table of Content

  • [Approach 1] Sorting then Searching for k consecutive elements - O(n*log(n)) time and O(1) space
  • [Approach 2] Using Hash Map - O(n*log n) time and O(n) space

[Approach 1] Sorting then Searching for k consecutive elements - O(n*log(n)) time and O(1) space

The main idea is to group the balls into sequences of k consecutive numbers without reusing any balls. The arr is first sorted to simplify finding consecutive groups. For each unused ball, the code tries to form a group of k consecutive balls by scanning forward. Balls are marked as -1 once used, and if any group can't be formed, the function returns false.

C++
#include <iostream> #include <vector> #include <algorithm>  using namespace std;   bool validgroup(vector<int> &arr, int k) {          // Sort the arr to make consecutive grouping easier     sort(arr.begin(), arr.end());      // Traverse the sorted arr     for (int i = 0; i < arr.size(); i++) {         // Skip if the card is already used         if (arr[i] == -1) continue;          // To track how many cards we added to the current group         int count = 0;                            // Starting value of current group         int curr = arr[i];                 // Try to form a group of size 'k'         for (int j = i; j < arr.size(); j++) {             if (arr[j] == curr) {                 count++;                 // Move to next consecutive card                 curr++;                            // Mark this card as used                 arr[j] = -1;                  }             if (count == k) break;         }          // If we couldn't form a full group of size k, return false         if (count != k) return false;     }      // All cards successfully grouped     return true; }  int main() {     vector<int> arr = {10, 1, 2, 11};     int k = 3;      // Check and print result     if (validgroup(arr, k)) {         cout << "true" << endl;     } else {         cout << "false" << endl;     }      return 0; } 
Java
import java.util.Arrays;  class GfG{      public static boolean validgroup(int[] arr, int k) {          // Sort the arr to make consecutive grouping easier         Arrays.sort(arr);          // Traverse the sorted arr         for (int i = 0; i < arr.length; i++) {             // Skip if the card is already used             if (arr[i] == -1) continue;              // To track how many cards we added to the current group             int count = 0;             // Starting value of current group             int curr = arr[i];              // Try to form a group of size 'k'             for (int j = i; j < arr.length; j++) {                 if (arr[j] == curr) {                     count++;                     // Move to next consecutive card                     curr++;                     // Mark this card as used                     arr[j] = -1;                 }                 if (count == k) break;             }              // If we couldn't form a full group of size k, return false             if (count != k) return false;         }          // All cards successfully grouped         return true;     }      public static void main(String[] args) {         int[] arr = {10, 1, 2, 11};         int k = 3;          // Check and print result         if (validgroup(arr, k)) {             System.out.println("true");         } else {             System.out.println("false");         }     } } 
Python
def validgroup(arr, k):     # Sort the arr to make consecutive grouping easier     arr.sort()      # Traverse the sorted arr     for i in range(len(arr)):         # Skip if the card is already used         if arr[i] == -1:             continue          # To track how many cards we added to the current group         count = 0         # Starting value of current group         curr = arr[i]          # Try to form a group of size 'k'         for j in range(i, len(arr)):             if arr[j] == curr:                 count += 1                 # Move to next consecutive card                 curr += 1                 # Mark this card as used                 arr[j] = -1             if count == k:                 break          # If we couldn't form a full group of size k, return False         if count != k:             return False      # All cards successfully grouped     return True  if __name__ == "__main__":     arr = [10, 1, 2, 11]     k = 3          # Check and print result     if validgroup(arr, k):         print("true")     else:         print("false") 
C#
using System;  class GfG {      public static bool validgroup(int[] arr, int k) {          // Sort the array to make consecutive grouping easier         Array.Sort(arr);          // Create a boolean array to mark used elements         bool[] used = new bool[arr.Length];          for (int i = 0; i < arr.Length; i++) {             // Skip if this number is already used in a group             if (used[i]) continue;              // Starting value of the current group             int curr = arr[i];             // Track how many numbers we've added to this group             int count = 0;              // Try to form a group of size k starting from current index             for (int j = 0; j < arr.Length; j++) {                 if (!used[j] && arr[j] == curr) {                     used[j] = true;                     curr++;                     count++;                 }                 if (count == k) break;             }              // If we couldn't form a full group of size k, return false             if (count != k) return false;         }          // All numbers successfully grouped         return true;     }      static void Main() {         int[] arr = {10, 1, 2, 11};         int k = 3;          // Check and print result         if (validgroup(arr, k)) {             Console.WriteLine("true");         } else {             Console.WriteLine("false");         }     } } 
JavaScript
function validgroup(arr, k) {          // Sort the arr to make consecutive grouping easier     arr.sort((a, b) => a - b);      // Traverse the sorted arr     for (let i = 0; i < arr.length; i++) {         // Skip if the card is already used         if (arr[i] === -1) continue;          // To track how many cards we added to the current group         let count = 0;         // Starting value of current group         let curr = arr[i];          // Try to form a group of size 'k'         for (let j = i; j < arr.length; j++) {             if (arr[j] === curr) {                 count++;                 // Move to next consecutive card                 curr++;                 // Mark this card as used                 arr[j] = -1;             }             if (count === k) break;         }          // If we couldn't form a full group of size k, return false         if (count !== k) return false;     }      // All cards successfully grouped     return true; }   // Driver Code  let arr = [10, 1, 2, 11]; let k = 3;  // Check and print result if (validgroup(arr, k)) {     console.log("true"); } else {     console.log("false"); } 

Output
true 

Time Complexity: O(n log n), due to sorting the array, while the rest of the logic runs in linear time as each element is visited at most once.
Auxiliary Space: O(1) extra space (in-place modifications using -1 as marker), ignoring input size. If input modification is not allowed, space becomes O(n) for a visited array or frequency map.

[Approach 2] Using Hash Map - O(n*log n) time and O(n) space

The idea is to store the frequency of each value in an ordered hash map. Then starting for each value and its frequency, check if consecutive values up to value + k - 1 have at least the same frequency.

Step-by-Step Approach:

  • Store the frequency of each value in an ordered hash map. Then start traversing the hash map from minimum value. We want to process the minimum values first in order to maintain the consecutive value order and ensure that no value is left unused.
  • For each value v and its frequency f, if the frequency is 0, it means that this value has already been used to create other groups, so continue.
  • Otherwise, starting from value = v +1 to value = v + k - 1, check if the frequency of these values is at least f. If yes, decrease the frequency by f. If not, return false as it is not possible to create consecutive groups starting from value v.
  • Return true if all values are processed.
C++
#include <iostream> #include <vector> #include <map> using namespace std;  bool validgroup(vector<int> &arr, int k) {     int n = arr.size();     map<int, int> freqMap;      // Store the frequency of each value      for (int val : arr) {         freqMap[val]++;     }      // Starting from minimum value, try to form consecutive groups     for (auto p : freqMap) {         int val = p.first;         int freq = p.second;          // Skip if all cards of this value are already used         if (freq == 0) continue;          // Try to form a group of 'k' starting from 'val'         for (int i = 1; i < k; i++) {             int nextVal = val + i;              // Check if there are enough cards for the next value             if (freqMap[nextVal] < freq) {                 return false;             }              // Deduct the used cards             freqMap[nextVal] -= freq;         }     }      return true; }  int main() {     vector<int> arr = {10, 1, 2, 11};     int k = 3;      if (validgroup(arr, k)) {         cout << "true" << endl;     } else {         cout << "false" << endl;     }      return 0; } 
Java
import java.util.TreeMap;  class GfG {          static boolean validgroup(int[] arr, int k) {         int n = arr.length;                  TreeMap<Integer, Integer> map = new TreeMap<>();                  // Store the frequency of each value          for (int val: arr) map.put(val, map.getOrDefault(val, 0) + 1);                  // Starting from minimum value, check if          // it is possible to create consecutive          // group with values upto value + k - 1.         for (var p: map.entrySet()) {             int val = p.getKey(), freq = p.getValue();                          // If frequency is 0, it means this value              // has already been used in another group              if (freq == 0) continue;                          // If there exists x occurences of val, then              // we need atleast x occurences of val+1, val+2              // , val+3, .... val+k-1.             for (int i = 1; i< k; i++) {                 int v = val + i;                 int f = map.getOrDefault(v, 0);                                  // If frequency is less than freq                  if (f < freq) {                     return false;                 }                                  map.put(v, f - freq);             }         }                  return true;     }      public static void main(String[] args) {         int[] arr = {10, 1, 2, 11};         int k = 3;         if (validgroup(arr, k)) {             System.out.println("true");         }         else {             System.out.println("false");         }     } } 
Python
from collections import defaultdict  def validgroup(arr, k):     n = len(arr)          map = defaultdict(int)          # Store the frequency of each value      for val in arr: map[val] += 1          # Starting from minimum value, check if      # it is possible to create consecutive      # group with values upto value + k - 1.     for val in sorted(map.keys()):         freq = map.get(val, 0)                  # If frequency is 0, it means this value          # has already been used in another group          if freq == 0: continue                  # If there exists x occurences of val, then          # we need atleast x occurences of val+1, val+2          # , val+3, .... val+k-1.         for i in range(1, k):             v = val + i             f = map.get(v, 0)                          # If frequency is less than freq              if f < freq:                 return False                          map[v] -= freq          return True  if __name__ == "__main__":     arr = [10, 1, 2, 11]     k = 3     if validgroup(arr, k):         print("true")     else:         print("false") 
C#
using System; using System.Collections.Generic;  class GfG {          static bool validgroup(int[] arr, int k) {         int n = arr.Length;          Dictionary<int, int> map = new Dictionary<int, int>();          // Store the frequency of each value          foreach (int val in arr) {             if (map.ContainsKey(val)) map[val]++;             else map[val] = 1;         }          // Get all unique keys and sort them         List<int> keys = new List<int>(map.Keys);         keys.Sort();          // Starting from minimum value, check if          // it is possible to create consecutive          // groups with values up to value + k - 1         foreach (int val in keys) {             int freq = map[val];              // If frequency is 0, it means this value              // has already been used in another group              if (freq == 0) continue;              // Try to form a group of size k starting from val             for (int i = 1; i < k; i++) {                 int nextVal = val + i;                 int nextFreq = map.ContainsKey(nextVal) ? map[nextVal] : 0;                  if (nextFreq < freq) return false;                  map[nextVal] = nextFreq - freq;             }         }          return true;     }      static void Main() {         int[] arr = {10, 1, 2, 11};         int k = 3;          if (validgroup(arr, k)) {             Console.WriteLine("true");         } else {             Console.WriteLine("false");         }     } } 
JavaScript
function  validgroup(arr, k) {     if (arr.length % k !== 0) return false;      let map = new Map();      // Store the frequency of each value      for (let val of arr) {         map.set(val, (map.get(val) || 0) + 1);     }      // Sort all keys (unique values)     let sortedKeys = [...map.keys()].sort((a, b) => a - b);      for (let val of sortedKeys) {         let freq = map.get(val);         if (freq === 0) continue;          // Try to form group of size k starting from val         for (let i = 0; i < k; i++) {             let currVal = val + i;             let currFreq = map.get(currVal) || 0;              if (currFreq < freq) return false;              map.set(currVal, currFreq - freq);         }     }      return true; }  let arr = [10, 1, 2, 11]; let k = 3; if (validgroup(arr, k)) {     console.log("true"); } else {     console.log("false"); } 

Output
true 

Next Article
Group Balls by Sequence

A

adityarana02
Improve
Article Tags :
  • Sorting
  • DSA
Practice Tags :
  • Sorting

Similar Reads

    Introduction to Sequences
    A sequence is a list of numbers arranged in a specific order, following a particular rule. Each number in the sequence is called a term. In mathematics, a sequence is an ordered list of numbers, where each number in the list is called a term. Sequences are defined by a specific rule that determines
    7 min read
    Group Anagrams Together
    Given an array of words arr[], the task is to groups strings that are anagrams. An anagram is a word or phrase formed by rearranging the letters of another, using all the original letters exactly once.Example:Input: arr[] = ["act", "god", "cat", "dog", "tac"]Output: [["act", "cat", "tac"], ["god", "
    7 min read
    Sequences and Series
    A sequence is an ordered list of numbers following a specific rule. Each number in a sequence is called a "term." The order in which terms are arranged is crucial, as each term has a specific position, often denoted as an​, where n indicates the position in the sequence.For example:2, 5, 8, 11, 14,
    10 min read
    What are Subsequences in an Array?
    Subsequences are a fundamental concept in computer science and programming when working with arrays. A subsequence of an array is a sequence of elements from the array that appear in the same order, but not necessarily consecutively. In this blog post, we'll discuss subsequences, covering their defi
    6 min read
    Minimum chairs for group timings
    Given an integer N representing the total size of groups S, their entry T1 and exit timings T2. This means that group number i will come at T1[i], leave at T2[i], and have a variable size in group S[i]. the task is to find the minimum number of chairs to be bought so that every customer has a chair
    6 min read
geeksforgeeks-footer-logo
Corporate & Communications Address:
A-143, 7th Floor, Sovereign Corporate Tower, Sector- 136, Noida, Uttar Pradesh (201305)
Registered Address:
K 061, Tower K, Gulshan Vivante Apartment, Sector 137, Noida, Gautam Buddh Nagar, Uttar Pradesh, 201305
GFG App on Play Store GFG App on App Store
Advertise with us
  • Company
  • About Us
  • Legal
  • Privacy Policy
  • In Media
  • Contact Us
  • Advertise with us
  • GFG Corporate Solution
  • Placement Training Program
  • Languages
  • Python
  • Java
  • C++
  • PHP
  • GoLang
  • SQL
  • R Language
  • Android Tutorial
  • Tutorials Archive
  • DSA
  • Data Structures
  • Algorithms
  • DSA for Beginners
  • Basic DSA Problems
  • DSA Roadmap
  • Top 100 DSA Interview Problems
  • DSA Roadmap by Sandeep Jain
  • All Cheat Sheets
  • Data Science & ML
  • Data Science With Python
  • Data Science For Beginner
  • Machine Learning
  • ML Maths
  • Data Visualisation
  • Pandas
  • NumPy
  • NLP
  • Deep Learning
  • Web Technologies
  • HTML
  • CSS
  • JavaScript
  • TypeScript
  • ReactJS
  • NextJS
  • Bootstrap
  • Web Design
  • Python Tutorial
  • Python Programming Examples
  • Python Projects
  • Python Tkinter
  • Python Web Scraping
  • OpenCV Tutorial
  • Python Interview Question
  • Django
  • Computer Science
  • Operating Systems
  • Computer Network
  • Database Management System
  • Software Engineering
  • Digital Logic Design
  • Engineering Maths
  • Software Development
  • Software Testing
  • DevOps
  • Git
  • Linux
  • AWS
  • Docker
  • Kubernetes
  • Azure
  • GCP
  • DevOps Roadmap
  • System Design
  • High Level Design
  • Low Level Design
  • UML Diagrams
  • Interview Guide
  • Design Patterns
  • OOAD
  • System Design Bootcamp
  • Interview Questions
  • Inteview Preparation
  • Competitive Programming
  • Top DS or Algo for CP
  • Company-Wise Recruitment Process
  • Company-Wise Preparation
  • Aptitude Preparation
  • Puzzles
  • School Subjects
  • Mathematics
  • Physics
  • Chemistry
  • Biology
  • Social Science
  • English Grammar
  • Commerce
  • World GK
  • GeeksforGeeks Videos
  • DSA
  • Python
  • Java
  • C++
  • Web Development
  • Data Science
  • CS Subjects
@GeeksforGeeks, Sanchhaya Education Private Limited, All rights reserved
We use cookies to ensure you have the best browsing experience on our website. By using our site, you acknowledge that you have read and understood our Cookie Policy & Privacy Policy
Lightbox
Improvement
Suggest Changes
Help us improve. Share your suggestions to enhance the article. Contribute your expertise and make a difference in the GeeksforGeeks portal.
geeksforgeeks-suggest-icon
Create Improvement
Enhance the article with your expertise. Contribute to the GeeksforGeeks community and help create better learning resources for all.
geeksforgeeks-improvement-icon
Suggest Changes
min 4 words, max Words Limit:1000

Thank You!

Your suggestions are valuable to us.

What kind of Experience do you want to share?

Interview Experiences
Admission Experiences
Career Journeys
Work Experiences
Campus Experiences
Competitive Exam Experiences