📜  所有非空子集总和的中位数

📅  最后修改于: 2021-05-14 01:16:14             🧑  作者: Mango

给定一个大小为N的数组arr [] ,任务是找到给定数组所有可能子集的和的中值。

例子:

天真的方法:解决此问题的最简单方法是生成给定数组的所有可能子集,并找到每个子集的元素之和。最后,打印所有可能的子集和的中值。

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

高效方法:为了优化上述方法,其思想是使用动态编程。以下是动态编程状态与基本情况的关系:

请按照以下步骤解决问题:

  • 初始化一个二维数组,例如DP [] [],以存储上述DP状态。
  • 使用DP状态之间的上述关系,以自下而上的方式填充所有dp [] []状态。
  • 初始化一个数组,例如sumSub [],以存储每个子集的所有可能的和。
  • 遍历dp [] []数组,并将所有可能的子集的和存储在sumSub []数组中。
  • sumSub []数组进行排序。
  • 最后,打印sumSub []数组的中间元素。
C++
// C++ program to implement
// the above approach
   
#include  
using namespace std; 
   
   
// Function to calculate the median of all 
// possible subsets by given operations
int findMedianOfsubSum(int arr[], int N)
{   
       
    // Stores sum of elements
    // of arr[]
    int sum=0;
       
       
    // Traverse the array arr[]
    for(int i=0; i < N; i++) {
           
           
       // Update sum
       sum += arr[i];
    }
       
       
    // Sort the array
    sort(arr, arr + N);
       
       
    // DP[i][j]: Stores total number of ways
    // to form the sum j by either selecting
    // ith element or not selecting ith item.
    int dp[N][sum+1];
       
       
    // Initialize all 
    // the DP states
    memset(dp, 0, sizeof(dp));
       
       
    // Base case
    for(int i=0; i < N; i++) {
           
           
       // Fill dp[i][0]
       dp[i][0] = 1;
    }
       
       
    // Base case
    dp[0][arr[0]] = 1;
       
       
    // Fill all the DP states based 
    // on the mentioned DP relation
    for(int i = 1; i < N; i++) {
           
        for(int j = 1; j <= sum; j++) {
               
               
            // If j is greater than
            // or equal to arr[i]
            if(j >= arr[i]) {
                   
                   
                // Update dp[i][j]    
                dp[i][j] = dp[i-1][j] + 
                      dp[i-1][j-arr[i]];
            }
            else {
                   
                   
                // Update dp[i][j]
                dp[i][j] = dp[i-1][j];
            }
        }
    }
       
       
    // Stores all possible
    // subset sum
    vector sumSub;
       
       
    // Traverse all possible subset sum
    for(int j=1; j <= sum; j++) {
           
           
       // Stores count of subsets 
       // whose sum is j
        int M = dp[N - 1][j];
           
           
       // Itearate over the range [1, M]
        for(int i = 1; i <= M; i++) {
               
               
            // Insert j into sumSub
            sumSub.push_back(j);
        }
    }
       
       
    // Stores middle element of sumSub 
    int mid = sumSub[sumSub.size() / 2];
       
    return mid; 
}
   
   
// Driver Code
int main()
{
    int arr[] = { 2, 3, 3 };
    int N = sizeof(arr) / sizeof(arr[0]);
    cout << findMedianOfsubSum(arr, N);
    return 0;
}


Java
// Java program to implement
// the above approach
import java.util.*;
 
class GFG{
     
// Function to calculate the median of all 
// possible subsets by given operations
static int findMedianOfsubSum(int arr[], int N)
{
     
    // Stores sum of elements
    // of arr[]
    int sum = 0;
       
    // Traverse the array arr[]
    for(int i = 0; i < N; i++)
    {
         
        // Update sum
        sum += arr[i];
    }
     
    // Sort the array
    Arrays.sort(arr);
     
    // DP[i][j]: Stores total number of ways
    // to form the sum j by either selecting
    // ith element or not selecting ith item.
    int [][]dp = new int[N][sum + 1];
     
    // Initialize all 
    // the DP states
    for(int i = 0; i < N; i++)
    {
        for(int j = 0; j < sum + 1; j++)
            dp[i][j] = 0;
    }
     
    // Base case
    for(int i = 0; i < N; i++)
    {
         
        // Fill dp[i][0]
        dp[i][0] = 1;
    }
     
    // Base case
    dp[0][arr[0]] = 1;
       
    // Fill all the DP states based 
    // on the mentioned DP relation
    for(int i = 1; i < N; i++)
    {
        for(int j = 1; j <= sum; j++)
        {
             
            // If j is greater than
            // or equal to arr[i]
            if (j >= arr[i])
            {
                 
                // Update dp[i][j]    
                dp[i][j] = dp[i - 1][j] + 
                           dp[i - 1][j - arr[i]];
            }
            else
            {
                 
                // Update dp[i][j]
                dp[i][j] = dp[i - 1][j];
            }
        }
    }
     
    // Stores all possible
    // subset sum
    Vector sumSub = new Vector();
     
    // Traverse all possible subset sum
    for(int j = 1; j <= sum; j++)
    {
         
        // Stores count of subsets 
        // whose sum is j
        int M = dp[N - 1][j];
         
        // Itearate over the range [1, M]
        for(int i = 1; i <= M; i++)
        {
             
            // Insert j into sumSub
            sumSub.add(j);
        }
    }
     
    // Stores middle element of sumSub 
    int mid = sumSub.get(sumSub.size() / 2);
       
    return mid; 
}
   
// Driver Code
public static void main(String args[])
{
    int arr[] = { 2, 3, 3 };
    int N = arr.length;
     
    System.out.print(findMedianOfsubSum(arr, N));
}
}
  
// This code is contributed by ipg2016107


Python3
# Python3 program to implement
# the above approach 
   
# Function to calculate the
# median of all possible subsets
# by given operations
def findMedianOfsubSum(arr, N):
   
    # Stores sum of elements
    # of arr[]
    sum = 0     
       
    # Traverse the array arr[]
    for i in range(N):
       
        # Update sum
        sum += arr[i]     
       
    # Sort the array
    arr.sort(reverse = False)      
       
    # DP[i][j]: Stores total number
    # of ways to form the sum j by
    # either selecting ith element
    # or not selecting ith item.
    dp = [[0 for i in range(sum + 1)]
             for j in range(N)]     
       
    # Base case
    for i in range(N):
       
        # Fill dp[i][0]
        dp[i][0] = 1     
       
    # Base case
    dp[0][arr[0]] = 1     
       
    # Fill all the DP states based 
    # on the mentioned DP relation
    for i in range(1, N, 1):
        for j in range(1, sum + 1, 1):
           
            # If j is greater than
            # or equal to arr[i]
            if(j >= arr[i]):
               
                # Update dp[i][j]    
                dp[i][j] = (dp[i - 1][j] +
                            dp[i - 1][j - arr[i]])
            else:
               
                # Update dp[i][j]
                dp[i][j] = dp[i - 1][j]
             
    # Stores all possible
    # subset sum
    sumSub = []     
       
    # Traverse all possible
    # subset sum
    for j in range(1, sum + 1, 1):
       
        # Stores count of subsets
        # whose sum is j
        M = dp[N - 1][j]         
            
        # Itearate over the
        # range [1, M]
        for i in range(1, M + 1, 1):
           
            # Insert j into sumSub
            sumSub.append(j)     
       
    # Stores middle element
    # of sumSub 
    mid = sumSub[len(sumSub) // 2]
       
    return mid 
   
# Driver Code
if __name__ == '__main__':
   
    arr = [2, 3, 3]
    N = len(arr)
    print(findMedianOfsubSum(arr, N))
     
# Thsi code is contributed by bgangwar59


C#
// C# program to implement
// the above approach 
using System;
using System.Collections.Generic;
  
class GFG{
  
// Function to calculate the median of all 
// possible subsets by given operations
static int findMedianOfsubSum(int[] arr, int N)
{
     
    // Stores sum of elements
    // of arr[]
    int sum = 0;
        
    // Traverse the array arr[]
    for(int i = 0; i < N; i++)
    {
         
        // Update sum
        sum += arr[i];
    }
      
    // Sort the array
    Array.Sort(arr);
      
    // DP[i][j]: Stores total number of ways
    // to form the sum j by either selecting
    // ith element or not selecting ith item.
    int [,]dp = new int[N, sum + 1];
      
    // Initialize all 
    // the DP states
    for(int i = 0; i < N; i++)
    {
        for(int j = 0; j < sum + 1; j++)
            dp[i, j] = 0;
    }
      
    // Base case
    for(int i = 0; i < N; i++)
    {
         
        // Fill dp[i][0]
        dp[i, 0] = 1;
    }
      
    // Base case
    dp[0, arr[0]] = 1;
        
    // Fill all the DP states based 
    // on the mentioned DP relation
    for(int i = 1; i < N; i++)
    {
        for(int j = 1; j <= sum; j++)
        {
             
            // If j is greater than
            // or equal to arr[i]
            if (j >= arr[i])
            {
                  
                // Update dp[i][j]    
                dp[i, j] = dp[i - 1, j] + 
                           dp[i - 1, j - arr[i]];
            }
            else
            {
                 
                // Update dp[i][j]
                dp[i, j] = dp[i - 1, j];
            }
        }
    }
      
    // Stores all possible
    // subset sum
    List sumSub = new List();
     
    // Traverse all possible subset sum
    for(int j = 1; j <= sum; j++)
    {
          
        // Stores count of subsets 
        // whose sum is j
        int M = dp[N - 1, j];
          
        // Itearate over the range [1, M]
        for(int i = 1; i <= M; i++)
        {
              
            // Insert j into sumSub
            sumSub.Add(j);
        }
    }
      
    // Stores middle element of sumSub 
    int mid = sumSub[sumSub.Count / 2];
        
    return mid; 
}
 
// Driver code
public static void Main()
{
    int[] arr = { 2, 3, 3 };
    int N = arr.Length;
      
    Console.Write(findMedianOfsubSum(arr, N));
}
}
 
// This code is contributed by sanjoy_62


输出
5