📌  相关文章
📜  将数组分成具有相等数量的唯一元素的两个子集

📅  最后修改于: 2021-10-28 01:32:23             🧑  作者: Mango

给定一个由N 个整数组成的数组arr[] ,任务是将数组划分为两个子集,使得两个子集中唯一元素的数量相同,对于每个元素,如果该元素属于第一个子集,则打印1 .否则,打印2 。如果无法进行这样的分区,则打印“-1”

例子:

朴素的方法:给定的问题可以通过将数组元素的所有可能分区生成为两个子集来解决,如果存在任何这样的分区,其不同元素的数量相同,则根据各自的集合数组元素所属打印12到。否则,打印“-1” ,因为不存在任何此类可能的数组分区。

时间复杂度: O(N*2 N )
辅助空间: O(N)

高效方法:如果频率是奇数,也可以通过查找唯一数组元素的频率来优化上述方法,则不存在这种可能的分区。否则,相应地打印子集的分区。请按照以下步骤解决问题:

  • 初始化一个 Map,比如M来存储所有数组元素的频率。
  • 初始化数组,比如ans[] ,它存储每个数组元素所属的子集数。
  • 通过对映射M中频率为1的元素进行计数,找出数组中唯一元素的计数。将此计数设为C
  • 如果C的值是偶数,则将这些元素的一半移动到第一个子集中,方法是将这些元素标记为1 ,并将数组ans[]中的所有元素其余为2
  • 否则,检查是否存在任何频率大于2 的元素,然后将该元素的一个实例移动到第二个子集。否则,打印“-1”

下面是上述方法的实现:

C++
// C++ program for the above approach
 
#include 
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 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 mp = new HashMap();
 
    // 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 mp = new Dictionary();
 
    // 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


输出:
1 1 1 2 1 1

时间复杂度: O(N)
辅助空间: O(1)

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程