Given an unsorted array with repetitions, the task is to group multiple occurrence of individual elements. The grouping should happen in a way that the order of first occurrences of all elements is maintained.
Examples:
Input: arr[] = {5, 3, 5, 1, 3, 3}
Output: {5, 5, 3, 3, 3, 1}
Input: arr[] = {4, 6, 9, 2, 3, 4, 9, 6, 10, 4}
Output: {4, 4, 4, 6, 6, 9, 9, 2, 3, 10}
Simple Solution is to use nested loops. The outer loop traverses array elements one by one. The inner loop checks if this is first occurrence, if yes, then the inner loop prints it and all other occurrences.
C++
#include<bits/stdc++.h>
using namespace std;
void groupElements( int arr[], int n)
{
bool *visited = new bool [n];
for ( int i=0; i<n; i++)
visited[i] = false ;
for ( int i=0; i<n; i++)
{
if (!visited[i])
{
cout << arr[i] << " " ;
for ( int j=i+1; j<n; j++)
{
if (arr[i] == arr[j])
{
cout << arr[i] << " " ;
visited[j] = true ;
}
}
}
}
delete [] visited;
}
int main()
{
int arr[] = {4, 6, 9, 2, 3, 4, 9, 6, 10, 4};
int n = sizeof (arr)/ sizeof (arr[0]);
groupElements(arr, n);
return 0;
}
|
Java
class GFG
{
static void groupElements( int arr[], int n)
{
boolean visited[] = new boolean [n];
for ( int i = 0 ; i < n; i++)
{
visited[i] = false ;
}
for ( int i = 0 ; i < n; i++)
{
if (!visited[i])
{
System.out.print(arr[i] + " " );
for ( int j = i + 1 ; j < n; j++)
{
if (arr[i] == arr[j])
{
System.out.print(arr[i] + " " );
visited[j] = true ;
}
}
}
}
}
public static void main(String[] args)
{
int arr[] = { 4 , 6 , 9 , 2 , 3 , 4 ,
9 , 6 , 10 , 4 };
int n = arr.length;
groupElements(arr, n);
}
}
|
Python3
def groupElements(arr, n):
visited = [ False ] * n
for i in range ( 0 , n):
visited[i] = False
for i in range ( 0 , n):
if (visited[i] = = False ):
print (arr[i], end = " " )
for j in range (i + 1 , n):
if (arr[i] = = arr[j]):
print (arr[i], end = " " )
visited[j] = True
arr = [ 4 , 6 , 9 , 2 , 3 ,
4 , 9 , 6 , 10 , 4 ]
n = len (arr)
groupElements(arr, n)
|
C#
using System;
class GFG
{
static void groupElements( int []arr, int n)
{
bool []visited = new bool [n];
for ( int i = 0; i < n; i++)
{
visited[i] = false ;
}
for ( int i = 0; i < n; i++)
{
if (!visited[i])
{
Console.Write(arr[i] + " " );
for ( int j = i + 1; j < n; j++)
{
if (arr[i] == arr[j])
{
Console.Write(arr[i] + " " );
visited[j] = true ;
}
}
}
}
}
public static void Main(String[] args)
{
int []arr = {4, 6, 9, 2, 3, 4,
9, 6, 10, 4};
int n = arr.Length;
groupElements(arr, n);
}
}
|
Javascript
<script>
function groupElements(arr, n)
{
let visited = Array(n).fill(0);
for (let i = 0; i < n; i++)
{
visited[i] = false ;
}
for (let i = 0; i < n; i++)
{
if (!visited[i])
{
document.write(arr[i] + " " );
for (let j = i + 1; j < n; j++)
{
if (arr[i] == arr[j])
{
document.write(arr[i] + " " );
visited[j] = true ;
}
}
}
}
}
let arr = [ 4, 6, 9, 2, 3, 4,
9, 6, 10, 4];
let n = arr.length;
groupElements(arr, n);
</script>
|
Output
4 4 4 6 6 9 9 2 3 10
Time complexity: O(n2)
As we are using nested loops.
Auxiliary Space: O(n)
The extra space is used to store the elements of the visited array;
Binary Search Tree based Method:
The time complexity can be improved to O(nLogn) using self-balancing binary search tree like Red-Black Tree or AVL tree. Following is complete algorithm.
- Create an empty Binary Search Tree (BST). Every BST node is going to contain an array element and its count.
- Traverse the input array and do following for every element.
- If element is not present in BST, then insert it with count as 0.
- If element is present, then increment count in corresponding BST node.
- Traverse the array again and do following for every element.
- If element is present in BST, then do following
- Get its count and print the element ‘count’ times.
- b) Delete the element from BST.
Time Complexity of the above solution is O(nLogn).
Hashing based Method: We can also use hashing. The idea is to replace Binary Search Tree with a Hash Map in above algorithm.
Below is Implementation of hashing based solution.
C++
#include<bits/stdc++.h>
using namespace std;
void orderedGroup(vector< int >&arr){
map< int , int >hM;
for ( int i=0;i<arr.size();i++){
hM[arr[i]]++;
}
for ( int i=0;i<arr.size();i++){
int count = (hM.find(arr[i]) == hM.end())? 0 : hM[arr[i]];
if (hM.find(arr[i]) != hM.end()){
for ( int j=0;j<count;j++){
cout<<arr[i]<< " " ;
}
hM.erase(arr[i]);
}
}
}
int main(){
vector< int >arr = {10, 5, 3, 10, 10, 4, 1, 3};
orderedGroup(arr);
}
|
Java
import java.util.HashMap;
class Main
{
static void orderedGroup( int arr[])
{
HashMap<Integer, Integer> hM = new HashMap<Integer, Integer>();
for ( int i= 0 ; i<arr.length; i++)
{
Integer prevCount = hM.get(arr[i]);
if (prevCount == null )
prevCount = 0 ;
hM.put(arr[i], prevCount + 1 );
}
for ( int i= 0 ; i<arr.length; i++)
{
Integer count = hM.get(arr[i]);
if (count != null )
{
for ( int j= 0 ; j<count; j++)
System.out.print(arr[i] + " " );
hM.remove(arr[i]);
}
}
}
public static void main (String[] args)
{
int arr[] = { 10 , 5 , 3 , 10 , 10 , 4 , 1 , 3 };
orderedGroup(arr);
}
}
|
Python3
def orderedGroup(arr):
hM = {}
for i in range ( 0 , len (arr)):
hM[arr[i]] = hM.get(arr[i], 0 ) + 1
for i in range ( 0 , len (arr)):
count = hM.get(arr[i], None )
if count ! = None :
for j in range ( 0 , count):
print (arr[i], end = " " )
del hM[arr[i]]
if __name__ = = "__main__" :
arr = [ 10 , 5 , 3 , 10 , 10 , 4 , 1 , 3 ]
orderedGroup(arr)
|
C#
using System;
using System.Collections.Generic;
class GFG
{
static void orderedGroup( int []arr)
{
Dictionary< int ,
int > hM = new Dictionary< int ,
int >();
for ( int i = 0; i < arr.Length; i++)
{
int prevCount = 0;
if (hM.ContainsKey(arr[i]))
prevCount = hM[arr[i]];
if (hM.ContainsKey(arr[i]))
hM[arr[i]] = prevCount + 1;
else
hM.Add(arr[i], prevCount + 1);
}
for ( int i = 0; i < arr.Length; i++)
{
int count = 0;
if (hM.ContainsKey(arr[i]))
count = hM[arr[i]];
if (count != 0)
{
for ( int j = 0; j < count; j++)
Console.Write(arr[i] + " " );
hM.Remove(arr[i]);
}
}
}
public static void Main (String[] args)
{
int []arr = {10, 5, 3, 10, 10, 4, 1, 3};
orderedGroup(arr);
}
}
|
Javascript
<script>
function orderedGroup(arr) {
var hM = {};
for ( var i = 0; i < arr.length; i++) {
var prevCount = 0;
if (hM.hasOwnProperty(arr[i])) prevCount = hM[arr[i]];
if (hM.hasOwnProperty(arr[i])) hM[arr[i]] = prevCount + 1;
else hM[arr[i]] = prevCount + 1;
}
for ( var i = 0; i < arr.length; i++) {
var count = 0;
if (hM.hasOwnProperty(arr[i])) count = hM[arr[i]];
if (count !== 0) {
for ( var j = 0; j < count; j++)
document.write(arr[i] + " " );
delete hM[arr[i]];
}
}
}
var arr = [10, 5, 3, 10, 10, 4, 1, 3];
orderedGroup(arr);
</script>
|
Output
10 10 10 5 3 3 4 1
Time Complexity of the above hashing based solution is ?(n) under the assumption that insert, search and delete operations on HashMap take O(1) time.
Auxiliary Space: O(n)
The extra space is used to store the elements in the map.
Below is a related problem for strings.
Group all occurrences of characters according to first appearance
This article is contributed by Himanshu Gupta. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.