📌  相关文章
📜  将数组拆分为两个等长的子集,使得一个数字的所有重复都位于一个子集中

📅  最后修改于: 2021-09-17 16:02:37             🧑  作者: Mango

给定一个由N 个整数组成的数组arr[] ,任务是检查是否可以将整数分成两个相等长度的子集,以便任何数组元素的所有重复都属于同一个子集。如果发现是真的,打印“是” 。否则,打印“否”

例子:

朴素方法:解决问题的最简单方法是尝试将数组拆分为两个相等子集的所有可能组合。对于每个组合,检查每个重复是否只属于两个集合中的一个。如果发现是真的,则打印“是” 。否则,打印“否”

时间复杂度: O(2 N ),其中 N 是给定整数的大小。
辅助空间: O(N)

有效的方法:可以通过将给定数组的所有元素的频率存储在数组freq[] 中来优化上述方法。要将元素分成两个相等的集合,每个集合中必须存在N/2 个元素。 因此,要将给定的数组arr[]分成2 个相等的部分, freq[]中必须有一些整数的子集,其总和为N/2 。请按照以下步骤解决问题:

  1. 将每个元素的频率存储在 Map M 中
  2. 现在,创建一个辅助数组aux[]并将其插入其中,所有频率都存储在Map 中
  3. 给定的问题简化为在数组aux[] 中找到具有给定总和N/2的子集。
  4. 如果上述步骤中存在任何这样的子集,则打印“是” 。否则,打印“否”

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
// Function to create the frequency
// array of the given array arr[]
vector findSubsets(vector arr, int N)
{
  // Hashmap to store the
  // frequencies
  map M;
  
  // Store freq for each element
  for (int i = 0; i < N; i++)
  {
      M[arr[i]]++;
  }
  
  // Get the total frequencies
  vector subsets;
  int I = 0;
  
  // Store frequencies in
  // subset[] array
  for(auto playerEntry = M.begin(); playerEntry != M.end(); playerEntry++)
  {
      subsets.push_back(playerEntry->second);
      I++;
  }
  
  // Return frequency array
  return subsets;
}
  
// Function to check is sum
// N/2 can be formed using
// some subset
bool subsetSum(vector subsets, int N, int target)
{
  // dp[i][j] store the answer to
  // form sum j using 1st i elements
  bool dp[N + 1][target + 1];
  
  // Initialize dp[][] with true
  for (int i = 0; i < N + 1; i++)
    dp[i][0] = true;
  
  // Fill the subset table in the
  // bottom up manner
  for (int i = 1; i <= N; i++)
  {
    for (int j = 1; j <= target; j++)
    {
      dp[i][j] = dp[i - 1][j];
  
      // If curren element is
      // less than j
      if (j >= subsets[i - 1])
      {
        // Update current state
        dp[i][j] |= dp[i - 1][j - subsets[i - 1]];
      }
    }
  }
  
  // Return the result
  return dp[N][target];
}
  
// Function to check if the given
// array can be split into required sets
void divideInto2Subset(vector arr, int N)
{
  // Store frequencies of arr[]
  vector subsets = findSubsets(arr, N);
  
  // If size of arr[] is odd then
  // print "Yes"
  if ((N) % 2 == 1)
  {
    cout << "No" << endl;
    return;
  }
   
  int subsets_size = subsets.size();
   
  // Check if answer is true or not
  bool isPossible = subsetSum(subsets, subsets_size, N / 2);
  
  // Print the result
  if (isPossible)
  {
    cout << "Yes" << endl;
  }
  else
  {
    cout << "No" << endl;
  }
}
 
int main()
{
      // Given array arr[]
      vector arr{2, 1, 2, 3};
       
      int N = arr.size();
       
      // Function Call
      divideInto2Subset(arr, N);
 
    return 0;
}


Java
// Java program for the above approach
import java.io.*;
import java.util.*;
 
class GFG {
 
    // Function to create the frequency
    // array of the given array arr[]
    private static int[] findSubsets(int[] arr)
    {
 
        // Hashmap to store the frequencies
        HashMap M
            = new HashMap<>();
 
        // Store freq for each element
        for (int i = 0; i < arr.length; i++) {
            M.put(arr[i],
                  M.getOrDefault(arr[i], 0) + 1);
        }
 
        // Get the total frequencies
        int[] subsets = new int[M.size()];
        int i = 0;
 
        // Store frequencies in subset[] array
        for (
            Map.Entry playerEntry :
            M.entrySet()) {
            subsets[i++]
                = playerEntry.getValue();
        }
 
        // Return frequency array
        return subsets;
    }
 
    // Function to check is sum N/2 can be
    // formed using some subset
    private static boolean
    subsetSum(int[] subsets,
              int target)
    {
 
        // dp[i][j] store the answer to
        // form sum j using 1st i elements
        boolean[][] dp
            = new boolean[subsets.length
                          + 1][target + 1];
 
        // Initialize dp[][] with true
        for (int i = 0; i < dp.length; i++)
            dp[i][0] = true;
 
        // Fill the subset table in the
        // bottom up manner
        for (int i = 1;
             i <= subsets.length; i++) {
 
            for (int j = 1;
                 j <= target; j++) {
                dp[i][j] = dp[i - 1][j];
 
                // If curren element is
                // less than j
                if (j >= subsets[i - 1]) {
 
                    // Update current state
                    dp[i][j]
                        |= dp[i - 1][j
                                     - subsets[i - 1]];
                }
            }
        }
 
        // Return the result
        return dp[subsets.length][target];
    }
 
    // Function to check if the given
    // array can be split into required sets
    public static void
    divideInto2Subset(int[] arr)
    {
        // Store frequencies of arr[]
        int[] subsets = findSubsets(arr);
 
        // If size of arr[] is odd then
        // print "Yes"
        if ((arr.length) % 2 == 1) {
            System.out.println("No");
            return;
        }
 
        // Check if answer is true or not
        boolean isPossible
            = subsetSum(subsets,
                        arr.length / 2);
 
        // Print the result
        if (isPossible) {
            System.out.println("Yes");
        }
        else {
            System.out.println("No");
        }
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        // Given array arr[]
        int[] arr = { 2, 1, 2, 3 };
 
        // Function Call
        divideInto2Subset(arr);
    }
}
 
// This code is contributed by divyesh072019


Python3
# Python3 program for the
# above approach
from collections import defaultdict
 
# Function to create the
# frequency array of the
# given array arr[]
def findSubsets(arr):
 
    # Hashmap to store
    # the frequencies
    M = defaultdict (int)
 
    # Store freq for each element
    for i in range (len(arr)):
        M[arr[i]] += 1
           
    # Get the total frequencies
    subsets = [0] * len(M)
    i = 0
 
    # Store frequencies in
    # subset[] array
    for j in M:
        subsets[i] = M[j]
        i += 1
 
    # Return frequency array
    return subsets
 
# Function to check is
# sum N/2 can be formed
# using some subset
def subsetSum(subsets, target):
 
    # dp[i][j] store the answer to
    # form sum j using 1st i elements
    dp = [[0 for x in range(target + 1)]
             for y in range(len(subsets) + 1)]
 
    # Initialize dp[][] with true
    for i in range(len(dp)):
        dp[i][0] = True
 
    # Fill the subset table in the
    # bottom up manner
    for i in range(1, len(subsets) + 1):
        for j in range(1, target + 1):
            dp[i][j] = dp[i - 1][j]
 
            # If current element is
            # less than j
            if (j >= subsets[i - 1]):
 
                # Update current state
                dp[i][j] |= (dp[i - 1][j -
                             subsets[i - 1]])
  
    # Return the result
    return dp[len(subsets)][target]
 
# Function to check if the given
# array can be split into required sets
def divideInto2Subset(arr):
 
    # Store frequencies of arr[]
    subsets = findSubsets(arr)
 
    # If size of arr[] is odd then
    # print "Yes"
    if (len(arr) % 2 == 1):
        print("No")
        return
    
    # Check if answer is true or not
    isPossible = subsetSum(subsets,
                           len(arr) // 2)
 
    # Print the result
    if (isPossible):
        print("Yes")   
    else :
        print("No")
 
# Driver Code
if __name__ == "__main__":
   
    # Given array arr
    arr = [2, 1, 2, 3]
 
    # Function Call
    divideInto2Subset(arr)
 
# This code is contributed by Chitranayal


C#
// C# program for the above
// approach
using System;
using System.Collections.Generic;  
class GFG{
   
// Function to create the frequency
// array of the given array arr[]
static int[] findSubsets(int[] arr)
{
  // Hashmap to store the
  // frequencies
  Dictionary M =  
             new Dictionary(); 
 
  // Store freq for each element
  for (int i = 0; i < arr.Length; i++)
  {
    if(M.ContainsKey(arr[i]))
    {
      M[arr[i]]++;
    }
    else
    {
      M[arr[i]] = 1;
    }
  }
 
  // Get the total frequencies
  int[] subsets = new int[M.Count];
  int I = 0;
 
  // Store frequencies in
  // subset[] array
  foreach(KeyValuePair
          playerEntry in M)
  {
    subsets[I] = playerEntry.Value;
    I++;
  }
 
  // Return frequency array
  return subsets;
}
 
// Function to check is sum
// N/2 can be formed using
// some subset
static bool subsetSum(int[] subsets,
                      int target)
{
  // dp[i][j] store the answer to
  // form sum j using 1st i elements
  bool[,] dp = new bool[subsets.Length + 1,
                        target + 1];
 
  // Initialize dp[][] with true
  for (int i = 0;
           i < dp.GetLength(0); i++)
    dp[i, 0] = true;
 
  // Fill the subset table in the
  // bottom up manner
  for (int i = 1;
           i <= subsets.Length; i++)
  {
    for (int j = 1; j <= target; j++)
    {
      dp[i, j] = dp[i - 1, j];
 
      // If curren element is
      // less than j
      if (j >= subsets[i - 1])
      {
        // Update current state
        dp[i, j] |= dp[i - 1,
                       j - subsets[i - 1]];
      }
    }
  }
 
  // Return the result
  return dp[subsets.Length,
            target];
}
 
// Function to check if the given
// array can be split into required sets
static void divideInto2Subset(int[] arr)
{
  // Store frequencies of arr[]
  int[] subsets = findSubsets(arr);
 
  // If size of arr[] is odd then
  // print "Yes"
  if ((arr.Length) % 2 == 1)
  {
    Console.WriteLine("No");
    return;
  }
 
  // Check if answer is true or not
  bool isPossible = subsetSum(subsets,
                              arr.Length / 2);
 
  // Print the result
  if (isPossible)
  {
    Console.WriteLine("Yes");
  }
  else
  {
    Console.WriteLine("No");
  }
}
     
// Driver code
static void Main()
{
  // Given array arr[]
  int[] arr = {2, 1, 2, 3};
 
  // Function Call
  divideInto2Subset(arr);
}
}
 
// This code is contributed by divyeshrabadiya07


Javascript


输出:
Yes

时间复杂度: O(N*M),其中 N 是数组的大小,M 是给定数组中不同元素的总数。
辅助空间: O(N)

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