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.
[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"); }
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"); }
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