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

📅  最后修改于: 2021-05-17 21:35:20             🧑  作者: 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


输出:
Yes

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