Given an array arr[] of distinct positive numbers, partition the array into minimum number of subsets (or subsequences) such that each subset contains consecutive numbers only.
Examples:
Input: arr[] = [100, 56, 5, 6, 102, 58, 101, 57, 7, 103, 59]
Output: 3
Explanation: [5, 6, 7], [ 56, 57, 58, 59] and [100, 101, 102, 103] are 3 subsets in which numbers are consecutive.
Input: arr[] = [10, 100, 105]
Output: 3
Explanation: [10], [100] and [105] are 3 subsets in which numbers are consecutive.
Table of Content
[Naive Approach] Sorting - O(n*log n) Time and O(1) Space
The idea is to sort the array and traverse the sorted array to count the number of such subsets.
Algorithm:
- Sort the array so that consecutive numbers come next to each other.
- Start with: count = 1, because at least one subset will always exist.
- Loop through the array from index
0ton-2. - At each step, compare: current with next.
- If arr[i] + 1 is not equal to arr[i + 1] that means sequence is broken, change count = count + 1.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int minSubsets(vector<int>& arr) {
// Sort the array so that consecutive elements
// become consecutive in the array.
sort(arr.begin(), arr.end());
int count = 1;
for (int i = 0; i < arr.size() - 1; i++) {
// Check if there's a break between
// consecutive numbers
if (arr[i] + 1 != arr[i + 1])
count++;
}
return count;
}
int main() {
vector<int> arr = {100, 56, 5, 6, 102, 58, 101, 57, 7, 103, 59};
cout << minSubsets(arr) << endl;
return 0;
}
import java.util.*;
class GfG {
static int minSubsets(int[] arr) {
// Sort the array so that consecutive elements
// become consecutive in the array.
Arrays.sort(arr);
int count = 1;
for (int i = 0; i < arr.length - 1; i++) {
// Check if there's a break between
// consecutive numbers
if (arr[i] + 1 != arr[i + 1])
count++;
}
return count;
}
public static void main(String[] args) {
int[] arr = { 100, 56, 5, 6, 102, 58,
101, 57, 7, 103, 59 };
System.out.println(minSubsets(arr));
}
}
def minSubsets(arr):
# Sort the array so that consecutive elements
# become consecutive in the array.
arr.sort()
count = 1
for i in range(len(arr) - 1):
# Check if there's a break between
# consecutive numbers
if arr[i] + 1 != arr[i + 1]:
count += 1
return count
if __name__ == "__main__":
arr = [100, 56, 5, 6, 102, 58, 101, 57, 7, 103, 59]
print(minSubsets(arr))
using System;
using System.Collections.Generic;
class GfG {
static int minSubsets(int[] arr) {
// Sort the array so that consecutive elements
// become consecutive in the array.
Array.Sort(arr);
int count = 1;
for(int i = 0; i < arr.Length - 1; i++) {
// Check if there's a break between
// consecutive numbers
if(arr[i] + 1 != arr[i + 1])
count++;
}
return count;
}
static void Main() {
int[] arr = {100, 56, 5, 6, 102, 58, 101, 57, 7, 103, 59};
Console.WriteLine(minSubsets(arr));
}
}
function minSubsets(arr) {
// Sort the array so that consecutive elements
// become consecutive in the array.
arr.sort((a, b) => a - b);
let count = 1;
for (let i = 0; i < arr.length - 1; i++) {
// Check if there's a break between
// consecutive numbers
if (arr[i] + 1 !== arr[i + 1])
count++;
}
return count;
}
// Driver Code
let arr = [ 100, 56, 5, 6, 102, 58, 101, 57, 7, 103, 59 ];
console.log(minSubsets(arr));
Output
3
[Expected Approach] Hashing - O(n) Time and O(n) Space
The idea is to use Hashing. We first insert all elements in a Hash Set. Then, traverse over all the elements and check if the current element can be a starting element of a consecutive subsequence.
- Store all the elements in a hash set to allow quick lookup.
- Traverse through each element and check if this element is starting point or not.
- To check starting, check if x - 1 is present in the set or not. If, not present that means x can become the starting point of longest consecutive subsequence.
- Once we find a starting point, increment the count.=
#include <iostream>
#include <vector>
#include <unordered_set>
using namespace std;
int minSubsets(vector<int>& arr) {
unordered_set<int> s(arr.begin(), arr.end());
int count = 0;
for(int x : arr) {
// Check for the start of a new subset
if(s.find(x - 1) == s.end()) {
count++;
}
}
return count;
}
int main() {
vector<int> arr = {100, 56, 5, 6, 102, 58, 101, 57, 7, 103};
cout << minSubsets(arr) << endl;
return 0;
}
import java.util.*;
class GfG {
static int minSubsets(int[] arr) {
// Create a HashSet from the array
Set<Integer> s = new HashSet<>();
for(int num : arr){
s.add(num);
}
int count = 0;
for(int x : arr){
// Check for the start of a new subset
if(!s.contains(x - 1)){
count++;
}
}
return count;
}
public static void main(String[] args){
int[] arr = {100, 56, 5, 6, 102, 58, 101, 57, 7, 103};
System.out.println(minSubsets(arr));
}
}
def minSubsets(arr):
# Create a set from the list
s = set(arr)
count = 0
for x in arr:
# Check for the start of a new subset
if (x - 1) not in s:
count += 1
return count
if __name__ == "__main__":
arr = [100, 56, 5, 6, 102, 58, 101, 57, 7, 103, 59]
print(minSubsets(arr))
using System;
using System.Collections.Generic;
class GfG {
static int countSubsets(int[] arr) {
// Create a HashSet from the list
HashSet<int> s = new HashSet<int>(arr);
int count = 0;
foreach(int x in arr){
// Check for the start of a new subset
if(!s.Contains(x - 1)){
count++;
}
}
return count;
}
static void Main(){
int[] arr = {100, 56, 5, 6, 102, 58, 101, 57, 7, 103};
Console.WriteLine(countSubsets(arr));
}
}
function minSubsets(arr) {
// Create a Set from the array
let s = new Set(arr);
let count = 0;
for(let x of arr){
// Check for the start of a new subset
if(!s.has(x - 1)){
count++;
}
}
return count;
}
// Driver Code
let arr = [100, 56, 5, 6, 102, 58, 101, 57, 7, 103];
console.log(minSubsets(arr));
Output
3