Partition an array into two subsets with equal count of unique elements
Last Updated :
16 Aug, 2022
Given an array arr[] consisting of N integers, the task is to partition the array into two subsets such that the count of unique elements in both the subsets is the same and for each element, print 1 if that element belongs to the first subset. Otherwise, print 2. If it is not possible to do such a partition, then print “-1”.
Examples:
Input: arr[] = {1, 1, 2, 3, 4, 4}
Output: 1 1 1 2 1 1
Explanation: Consider the first and the second subset of the partition of the array as {1, 1, 2, 4 4} and {3}. Now, the above partition of subsets has equal count of distinct elements..
Input: arr[] = {1, 1, 2, 2, 3}
Output: -1
Naive Approach: The given problem can be solved by generating all possible partition of the array elements into two subsets and if there exists any such partition whose count of distinct elements are the same, then print 1 and 2 according to the respective set array elements belongs to. Otherwise, print “-1” as there doesn’t exist any such possible partition of the array.
Time Complexity: O(N*2N)
Auxiliary Space: O(N)
Efficient Approach: The above approach can also be optimized by finding the frequency of unique array elements if the frequency is odd, then there no such possible partition. Otherwise, print the partition of the subset accordingly. Follow the steps below to solve the problem:
- Initialize a Map, say M to store the frequency of all array elements.
- Initialize the array, say ans[] that stores the subset number where each array element belongs to.
- Find the count of the unique elements in the array by count the element having frequency 1 in the map M. Let this count be C.
- If the value of C is even, then move half of these elements into the first subset by marking those elements as 1 and rest all elements as 2 in the array ans[].
- Otherwise, check if there exist any element having a frequency greater than 2, then shift one instance of that element to the second subset. Otherwise, print “-1”.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
void arrayPartition( int a[], int n)
{
int ans[n];
int cnt = 0;
int ind, flag = 0;
map< int , int > mp;
for ( int i = 0; i < n; i++) {
mp[a[i]]++;
}
for ( int i = 0; i < n; i++) {
if (mp[a[i]] == 1)
cnt++;
if (mp[a[i]] > 2 && flag == 0) {
flag = 1;
ind = i;
}
}
int p = (cnt + 1) / 2;
int ans1 = 0;
for ( int i = 0; i < n; i++)
ans[i] = 1;
for ( int i = 0; i < n; i++) {
if (mp[a[i]] == 1 && ans1 < p) {
ans[i] = 1;
ans1++;
}
else if (mp[a[i]] == 1) {
ans[i] = 2;
}
}
if (cnt % 2 == 1 && flag == 0) {
cout << -1 << endl;
return ;
}
if (cnt % 2 == 0) {
for ( int i = 0; i < n; i++) {
cout << ans[i] << " " ;
}
}
else {
for ( int i = 0; i < n; i++) {
if (ind == i)
cout << 2 << " " ;
else
cout << ans[i] << " " ;
}
}
}
int main()
{
int arr[] = { 1, 1, 2, 3, 4, 4 };
int N = sizeof (arr) / sizeof (arr[0]);
arrayPartition(arr, N);
return 0;
}
|
Java
import java.util.HashMap;
class GFG{
public static void arrayPartition( int a[], int n)
{
int [] ans = new int [n];
int cnt = 0 ;
int ind = 0 , flag = 0 ;
HashMap<Integer, Integer> mp = new HashMap<Integer, Integer>();
for ( int i = 0 ; i < n; i++) {
if (mp.containsKey(a[i])){
mp.put(a[i], mp.get(a[i]) + 1 );
} else {
mp.put(a[i], 1 );
}
}
for ( int i = 0 ; i < n; i++) {
if (mp.get(a[i]) == 1 )
cnt++;
if (mp.get(a[i]) > 2 && flag == 0 ) {
flag = 1 ;
ind = i;
}
}
int p = (cnt + 1 ) / 2 ;
int ans1 = 0 ;
for ( int i = 0 ; i < n; i++)
ans[i] = 1 ;
for ( int i = 0 ; i < n; i++) {
if (mp.get(a[i]) == 1 && ans1 < p) {
ans[i] = 1 ;
ans1++;
}
else if (mp.get(a[i]) == 1 ) {
ans[i] = 2 ;
}
}
if (cnt % 2 == 1 && flag == 0 ) {
System.out.println(- 1 + "\n" );
return ;
}
if (cnt % 2 == 0 ) {
for ( int i = 0 ; i < n; i++) {
System.out.print(ans[i] + " " );
}
}
else {
for ( int i = 0 ; i < n; i++) {
if (ind == i)
System.out.print( 2 + " " );
else
System.out.print(ans[i] + " " );
}
}
}
public static void main(String args[])
{
int arr[] = { 1 , 1 , 2 , 3 , 4 , 4 };
int N = arr.length;
arrayPartition(arr, N);
}
}
|
Python3
def arrayPartition(a, n):
ans = [ 0 ] * n
cnt = 0
ind, flag = 0 , 0
mp = {}
for i in a:
mp[i] = mp.get(i, 0 ) + 1
for i in range (n):
if ((a[i] in mp) and mp[a[i]] = = 1 ):
cnt + = 1
if (mp[a[i]] > 2 and flag = = 0 ):
flag = 1
ind = i
p = (cnt + 1 ) / / 2
ans1 = 0
for i in range (n):
ans[i] = 1
for i in range (n):
if ((a[i] in mp) and mp[a[i]] = = 1 and
ans1 < p):
ans[i] = 1
ans1 + = 1
elif ((a[i] in mp) and mp[a[i]] = = 1 ):
ans[i] = 2
if (cnt % 2 = = 1 and flag = = 0 ):
print ( - 1 )
return
if (cnt % 2 = = 0 ):
print ( * ans)
else :
for i in range (n):
if (ind = = i):
print ( 2 , end = " " )
else :
print (ans[i], end = " " )
if __name__ = = '__main__' :
arr = [ 1 , 1 , 2 , 3 , 4 , 4 ]
N = len (arr)
arrayPartition(arr, N)
|
C#
using System;
using System.Collections.Generic;
class GFG{
static void arrayPartition( int []a, int n)
{
int []ans = new int [n];
int cnt = 0;
int ind=0, flag = 0;
Dictionary< int , int > mp = new Dictionary< int , int >();
for ( int i = 0; i < n; i++) {
if (mp.ContainsKey(a[i]))
mp[a[i]]++;
else
mp.Add(a[i],1);
}
for ( int i = 0; i < n; i++) {
if (mp.ContainsKey(a[i]) && mp[a[i]] == 1)
cnt++;
if (mp.ContainsKey(a[i]) && mp[a[i]] > 2 && flag == 0) {
flag = 1;
ind = i;
}
}
int p = (cnt + 1) / 2;
int ans1 = 0;
/// array ans[] as 1
for ( int i = 0; i < n; i++)
ans[i] = 1;
for ( int i = 0; i < n; i++) {
if (mp.ContainsKey(a[i]) && mp[a[i]] == 1 && ans1 < p) {
ans[i] = 1;
ans1++;
}
else if (mp.ContainsKey(a[i]) && mp[a[i]] == 1) {
ans[i] = 2;
}
}
if (cnt % 2 == 1 && flag == 0) {
Console.Write(-1);
return ;
}
if (cnt % 2 == 0) {
for ( int i = 0; i < n; i++) {
Console.Write(ans[i] + " " );
}
}
else {
for ( int i = 0; i < n; i++) {
if (ind == i)
Console.Write(2 + " " );
else
Console.Write(ans[i] + " " );
}
}
}
public static void Main()
{
int []arr = { 1, 1, 2, 3, 4, 4 };
int N = arr.Length;
arrayPartition(arr, N);
}
}
|
Javascript
<script>
function arrayPartition(a, n) {
let ans = new Array(n);
let cnt = 0;
let ind, flag = 0;
let mp = new Map();
for (let i = 0; i < n; i++) {
if (mp.has(a[i])) {
mp.set(a[i], mp.get(a[i]) + 1)
} else {
mp.set(a[i], 1)
}
}
for (let i = 0; i < n; i++) {
if (mp.get(a[i]) == 1)
cnt++;
if (mp.get(a[i]) > 2 && flag == 0) {
flag = 1;
ind = i;
}
}
let p = Math.floor((cnt + 1) / 2);
let ans1 = 0;
for (let i = 0; i < n; i++)
ans[i] = 1;
for (let i = 0; i < n; i++) {
if (mp.get(a[i]) == 1 && ans1 < p) {
ans[i] = 1;
ans1++;
}
else if (mp.get(a[i]) == 1) {
ans[i] = 2;
}
}
if (cnt % 2 == 1 && flag == 0) {
document.write(-1 + "<br>" );
return ;
}
if (cnt % 2 == 0) {
for (let i = 0; i < n; i++) {
document.write(ans[i] + " " );
}
}
else {
for (let i = 0; i < n; i++) {
if (ind == i)
document.write(2 + " " );
else
document.write(ans[i] << " " );
}
}
}
let arr = [1, 1, 2, 3, 4, 4];
let N = arr.length
arrayPartition(arr, N);
</script>
|
Time Complexity: O(NlogN)
Auxiliary Space: O(N) as using extra space for Map
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...