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++
// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
// Function to partition the array into
// two subsets such that count of unique
// elements in both subsets is the same
void arrayPartition(int a[], int n)
{
// Stores the subset number for
// each array elements
int ans[n];
// Stores the count of unique
// array elements
int cnt = 0;
int ind, flag = 0;
// Stores the frequency of elements
map<int, int> mp;
// Traverse the array
for (int i = 0; i < n; i++) {
mp[a[i]]++;
}
// Count of elements having a
// frequency of 1
for (int i = 0; i < n; i++) {
if (mp[a[i]] == 1)
cnt++;
// Check if there exists any
// element with frequency > 2
if (mp[a[i]] > 2 && flag == 0) {
flag = 1;
ind = i;
}
}
// Count of elements needed to
// have frequency exactly 1 in
// each subset
int p = (cnt + 1) / 2;
int ans1 = 0;
// Initialize all values in the
/// array ans[] as 1
for (int i = 0; i < n; i++)
ans[i] = 1;
// Traverse the array ans[]
for (int i = 0; i < n; i++) {
// This array element is a
// part of first subset
if (mp[a[i]] == 1 && ans1 < p) {
ans[i] = 1;
ans1++;
}
// Half array elements with
// frequency 1 are part of
// the second subset
else if (mp[a[i]] == 1) {
ans[i] = 2;
}
}
// If count of elements is exactly
// 1 are odd and has no element
// with frequency > 2
if (cnt % 2 == 1 && flag == 0) {
cout << -1 << endl;
return;
}
// If count of elements that occurs
// exactly once are even
if (cnt % 2 == 0) {
// Print the result
for (int i = 0; i < n; i++) {
cout << ans[i] << " ";
}
}
// If the count of elements has
// exactly 1 frequency are odd
// and there is an element with
// frequency greater than 2
else {
// Print the result
for (int i = 0; i < n; i++) {
if (ind == i)
cout << 2 << " ";
else
cout << ans[i] << " ";
}
}
}
// Driver Codea
int main()
{
int arr[] = { 1, 1, 2, 3, 4, 4 };
int N = sizeof(arr) / sizeof(arr[0]);
arrayPartition(arr, N);
return 0;
}
Java
// Java program for the above approach
import java.util.HashMap;
class GFG{
// Function to partition the array into
// two subsets such that count of unique
// elements in both subsets is the same
public static void arrayPartition(int a[], int n)
{
// Stores the subset number for
// each array elements
int[] ans = new int[n];
// Stores the count of unique
// array elements
int cnt = 0;
int ind = 0, flag = 0;
// Stores the frequency of elements
HashMap<Integer, Integer> mp = new HashMap<Integer, Integer>();
// Traverse the array
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);
}
}
// Count of elements having a
// frequency of 1
for (int i = 0; i < n; i++) {
if (mp.get(a[i]) == 1)
cnt++;
// Check if there exists any
// element with frequency > 2
if (mp.get(a[i]) > 2 && flag == 0) {
flag = 1;
ind = i;
}
}
// Count of elements needed to
// have frequency exactly 1 in
// each subset
int p = (cnt + 1) / 2;
int ans1 = 0;
// Initialize all values in the
/// array ans[] as 1
for (int i = 0; i < n; i++)
ans[i] = 1;
// Traverse the array ans[]
for (int i = 0; i < n; i++) {
// This array element is a
// part of first subset
if (mp.get(a[i]) == 1 && ans1 < p) {
ans[i] = 1;
ans1++;
}
// Half array elements with
// frequency 1 are part of
// the second subset
else if (mp.get(a[i]) == 1) {
ans[i] = 2;
}
}
// If count of elements is exactly
// 1 are odd and has no element
// with frequency > 2
if (cnt % 2 == 1 && flag == 0) {
System.out.println(-1 + "\n");
return;
}
// If count of elements that occurs
// exactly once are even
if (cnt % 2 == 0) {
// Print the result
for (int i = 0; i < n; i++) {
System.out.print(ans[i] + " ");
}
}
// If the count of elements has
// exactly 1 frequency are odd
// and there is an element with
// frequency greater than 2
else {
// Print the result
for (int i = 0; i < n; i++) {
if (ind == i)
System.out.print(2 + " ");
else
System.out.print(ans[i] + " ");
}
}
}
// Driver Codea
public static void main(String args[])
{
int arr[] = { 1, 1, 2, 3, 4, 4 };
int N = arr.length;
arrayPartition(arr, N);
}
}
// This code is contributed by gfgking.
Python3
# Python3 program for the above approach
# Function to partition the array into
# two subsets such that count of unique
# elements in both subsets is the same
def arrayPartition(a, n):
# Stores the subset number for
# each array elements
ans = [0] * n
# Stores the count of unique
# array elements
cnt = 0
ind, flag = 0, 0
# Stores the frequency of elements
mp = {}
# Traverse the array
for i in a:
mp[i] = mp.get(i, 0) + 1
# Count of elements having a
# frequency of 1
for i in range(n):
if ((a[i] in mp) and mp[a[i]] == 1):
cnt += 1
# Check if there exists any
# element with frequency > 2
if (mp[a[i]] > 2 and flag == 0):
flag = 1
ind = i
# Count of elements needed to
# have frequency exactly 1 in
# each subset
p = (cnt + 1) // 2
ans1 = 0
# Initialize all values in the
# array ans[] as 1
for i in range(n):
ans[i] = 1
# Traverse the array ans[]
for i in range(n):
# This array element is a
# part of first subset
if ((a[i] in mp) and mp[a[i]] == 1 and
ans1 < p):
ans[i] = 1
ans1 += 1
# Half array elements with
# frequency 1 are part of
# the second subset
elif ((a[i] in mp) and mp[a[i]] == 1):
ans[i] = 2
# If count of elements is exactly
# 1 are odd and has no element
# with frequency > 2
if (cnt % 2 == 1 and flag == 0):
print (-1)
return
# If count of elements that occurs
# exactly once are even
if (cnt % 2 == 0):
# Print the result
print(*ans)
# If the count of elements has
# exactly 1 frequency are odd
# and there is an element with
# frequency greater than 2
else:
# Print the result
for i in range(n):
if (ind == i):
print(2, end = " ")
else:
print(ans[i], end = " ")
# Driver Codea
if __name__ == '__main__':
arr = [ 1, 1, 2, 3, 4, 4 ]
N = len(arr)
arrayPartition(arr, N)
# This code is contributed by mohit kumar 29
C#
// C# program for the above approach
using System;
using System.Collections.Generic;
class GFG{
// Function to partition the array into
// two subsets such that count of unique
// elements in both subsets is the same
static void arrayPartition(int []a, int n)
{
// Stores the subset number for
// each array elements
int []ans = new int[n];
// Stores the count of unique
// array elements
int cnt = 0;
int ind=0, flag = 0;
// Stores the frequency of elements
Dictionary<int,int> mp = new Dictionary<int,int>();
// Traverse the array
for (int i = 0; i < n; i++) {
if(mp.ContainsKey(a[i]))
mp[a[i]]++;
else
mp.Add(a[i],1);
}
// Count of elements having a
// frequency of 1
for (int i = 0; i < n; i++) {
if (mp.ContainsKey(a[i]) && mp[a[i]] == 1)
cnt++;
// Check if there exists any
// element with frequency > 2
if (mp.ContainsKey(a[i]) && mp[a[i]] > 2 && flag == 0) {
flag = 1;
ind = i;
}
}
// Count of elements needed to
// have frequency exactly 1 in
// each subset
int p = (cnt + 1) / 2;
int ans1 = 0;
// Initialize all values in the
/// array ans[] as 1
for (int i = 0; i < n; i++)
ans[i] = 1;
// Traverse the array ans[]
for (int i = 0; i < n; i++) {
// This array element is a
// part of first subset
if (mp.ContainsKey(a[i]) && mp[a[i]] == 1 && ans1 < p) {
ans[i] = 1;
ans1++;
}
// Half array elements with
// frequency 1 are part of
// the second subset
else if (mp.ContainsKey(a[i]) && mp[a[i]] == 1) {
ans[i] = 2;
}
}
// If count of elements is exactly
// 1 are odd and has no element
// with frequency > 2
if (cnt % 2 == 1 && flag == 0) {
Console.Write(-1);
return;
}
// If count of elements that occurs
// exactly once are even
if (cnt % 2 == 0) {
// Print the result
for (int i = 0; i < n; i++) {
Console.Write(ans[i] + " ");
}
}
// If the count of elements has
// exactly 1 frequency are odd
// and there is an element with
// frequency greater than 2
else {
// Print the result
for (int i = 0; i < n; i++) {
if (ind == i)
Console.Write(2 + " ");
else
Console.Write(ans[i] + " ");
}
}
}
// Driver Codea
public static void Main()
{
int []arr = { 1, 1, 2, 3, 4, 4 };
int N = arr.Length;
arrayPartition(arr, N);
}
}
// This code is contributed by SURENDRA_GANGWAR.
JavaScript
<script>
// JavaScript program for the above approach
// Function to partition the array into
// two subsets such that count of unique
// elements in both subsets is the same
function arrayPartition(a, n) {
// Stores the subset number for
// each array elements
let ans = new Array(n);
// Stores the count of unique
// array elements
let cnt = 0;
let ind, flag = 0;
// Stores the frequency of elements
let mp = new Map();
// Traverse the array
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)
}
}
// Count of elements having a
// frequency of 1
for (let i = 0; i < n; i++) {
if (mp.get(a[i]) == 1)
cnt++;
// Check if there exists any
// element with frequency > 2
if (mp.get(a[i]) > 2 && flag == 0) {
flag = 1;
ind = i;
}
}
// Count of elements needed to
// have frequency exactly 1 in
// each subset
let p = Math.floor((cnt + 1) / 2);
let ans1 = 0;
// Initialize all values in the
/// array ans[] as 1
for (let i = 0; i < n; i++)
ans[i] = 1;
// Traverse the array ans[]
for (let i = 0; i < n; i++) {
// This array element is a
// part of first subset
if (mp.get(a[i]) == 1 && ans1 < p) {
ans[i] = 1;
ans1++;
}
// Half array elements with
// frequency 1 are part of
// the second subset
else if (mp.get(a[i]) == 1) {
ans[i] = 2;
}
}
// If count of elements is exactly
// 1 are odd and has no element
// with frequency > 2
if (cnt % 2 == 1 && flag == 0) {
document.write(-1 + "<br>");
return;
}
// If count of elements that occurs
// exactly once are even
if (cnt % 2 == 0) {
// Print the result
for (let i = 0; i < n; i++) {
document.write(ans[i] + " ");
}
}
// If the count of elements has
// exactly 1 frequency are odd
// and there is an element with
// frequency greater than 2
else {
// Print the result
for (let i = 0; i < n; i++) {
if (ind == i)
document.write(2 + " ");
else
document.write(ans[i] << " ");
}
}
}
// Driver Codea
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
Similar Reads
Count of Subsets that can be partitioned into two non empty sets with equal Sum Given an array Arr[] of size N, the task is to find the count of subsets of Arr[] that can be partitioned into two non-empty groups having equal sum. Examples: Input: Arr[] = {2, 3, 4, 5}Output: 2Explanation: The subsets are: {2, 3, 5} which can be split into {2, 3} and {5}{2, 3, 4, 5} which can be
15+ min read
Remove element such that Array cannot be partitioned into two subsets with equal sum Given an array arr[] of N size, the task is to remove an element such that the array cannot be partitioned into two groups with equal sum. Note: If no element is required to remove, return -1. Examples: Input: arr[] = {4, 4, 8}, N = 3Output: 4Explanation: Two groups with equal sum are: G1 = {4, 4},
8 min read
Partition of a set into k subsets with equal sum using BitMask and DP Given an integer array arr[] and an integer k, the task is to check if it is possible to divide the given array into k non-empty subsets of equal sum such that every array element is part of a single subset.Examples: Input: arr[] = [2, 1, 4, 5, 6], k = 3 Output: trueExplanation: Possible subsets of
9 min read
Partition of a set into K subsets with equal sum Given an integer array arr[] and an integer k, the task is to check if it is possible to divide the given array into k non-empty subsets of equal sum such that every array element is part of a single subset.Examples: Input: arr[] = [2, 1, 4, 5, 6], k = 3 Output: trueExplanation: Possible subsets of
9 min read
Count of unique subsets from a set having repeated elements Given an array arr[] of size N. The task is to count the number of unique subsets. Examples: Input: arr[] = {1, 2, 2}Output: 6Explanation: Total possible subsets of this set = 2³= 8. Following are the all 8 subsets formed from arr[].{}, {1}, {2}, {2}, {1, 2}, {1, 2}, {2, 2}, {1, 2, 2}. These are all
5 min read
Count pairs in an array such that both elements has equal set bits Given an array arr [] of size N with unique elements, the task is to count the total number of pairs of elements that have equal set bits count. Examples: Input: arr[] = {2, 5, 8, 1, 3} Output: 4 Set bits counts for {2, 5, 8, 1, 3} are {1, 2, 1, 1, 2} All pairs with same set bits count are {2, 8}, {
6 min read
Find an element which divides the array in two subarrays with equal product Given, an array of size N. Find an element which divides the array into two sub-arrays with equal product. Print -1 if no such partition is not possible. Examples : Input : 1 4 2 1 4 Output : 2 If 2 is the partition, subarrays are : {1, 4} and {1, 4} Input : 2, 3, 4, 1, 4, 6 Output : 1 If 1 is the p
12 min read
Count ways to split array into two subarrays with equal GCD Given an array, arr[] of size N, the task is to count the number of ways to split given array elements into two subarrays such that GCD of both the subarrays are equal. Examples: Input: arr[] = {8, 4, 4, 8, 12} Output: 2 Explanation: Possible ways to split the array two groups of equal GCD are: { {{
8 min read
Partition a Set into Two Subsets of Equal Sum Given an array arr[], the task is to check if it can be partitioned into two parts such that the sum of elements in both parts is the same.Note: Each element is present in either the first subset or the second subset, but not in both.Examples: Input: arr[] = [1, 5, 11, 5]Output: true Explanation: Th
15+ min read
Minimize sum of count of unique elements in Array after dividing into [1, N] subsets Given an array arr[] of length N, the task is to find the minimum number of unique elements possible in total when the array is divided into K subsets (for all K in the range [1, N]) i.e. sum of count of unique elements present in each subset after dividing the given array into K subsets. Examples:
7 min read