📌  相关文章
📜  总和至少为 0 的 Array 的最大子集

📅  最后修改于: 2022-05-13 01:56:05.993000             🧑  作者: Mango

总和至少为 0 的 Array 的最大子集

给定一个包含N个整数的数组arr[] ,任务是找到总和至少为 0 的最大子集。

例子:

Naive Approach:解决问题的基本思想是基于以下思想使用递归:

请按照以下步骤操作:

  • 使用递归函数,对于每个索引,有两种选择,要么选择该元素,要么不选择该元素。
  • 避免选择该元素,其值使总和为负。
  • 从两个选项中返回最大选取元素的计数。
  • 所有这些中的最大值是所需的子集大小。

下面是上述方法的实现:

C++
// C++ code to implement the approach
 
#include 
using namespace std;
 
// Function to return maximum count
int pick_max_elements(int pos, int sum,
                      int n, int arr[])
{
 
    // Return if the end of the array
    // is reached
    if (pos == n)
        return 0;
 
    int taken = INT_MIN;
 
    // If we select element at index pos
    if (sum + arr[pos] >= 0)
        taken = 1
                + pick_max_elements(pos + 1,
                                    sum + arr[pos],
                                    n, arr);
 
    int not_taken
        = pick_max_elements(pos + 1,
                            sum, n, arr);
 
    // Return the maximize steps taken
    return max(taken, not_taken);
}
 
// Driver code
int main()
{
    int arr[] = { 1, -4, -2, -3 };
    int N = sizeof(arr) / sizeof(arr[0]);
 
    // Function to pick maximum number
    // of elements
    cout << pick_max_elements(0, 0, N, arr);
    return 0;
}


Java
// Java code to implement the approach
import java.util.*;
class GFG
{
 
  // Function to return maximum count
  public static int pick_max_elements(int pos, int sum,
                                      int n, int arr[])
  {
 
    // Return if the end of the array
    // is reached
    if (pos == n)
      return 0;
 
    int taken = Integer.MIN_VALUE;
 
    // If we select element at index pos
    if (sum + arr[pos] >= 0)
      taken = 1
      + pick_max_elements(
      pos + 1, sum + arr[pos], n, arr);
 
    int not_taken
      = pick_max_elements(pos + 1, sum, n, arr);
 
    // Return the maximize steps taken
    return Math.max(taken, not_taken);
  }
 
  // Driver code
  public static void main(String[] args)
  {
    int arr[] = { 1, -4, -2, -3 };
    int N = arr.length;
 
    // Function to pick maximum number
    // of elements
    System.out.print(pick_max_elements(0, 0, N, arr));
  }
}
 
// This code is contributed by Taranpreet


Python
# Python code to implement the approach
INT_MIN = -(1e9 + 7)
 
# Function to return maximum count
def pick_max_elements(pos, sum, n, arr):
 
    # Return if the end of the array
    # is reached
    if (pos == n):
        return 0
 
    taken = INT_MIN
 
    # If we select element at index pos
    if (sum + arr[pos] >= 0):
        taken = 1 + pick_max_elements(pos + 1, sum + arr[pos], n, arr)
 
    not_taken = pick_max_elements(pos + 1, sum, n, arr)
 
    # Return the maximize steps taken
    return max(taken, not_taken)
 
# Driver code
arr = [1, -4, -2, -3]
N = len(arr)
 
# Function to pick maximum number
# of elements
print(pick_max_elements(0, 0, N, arr))
 
# This code is contributed by Samim Hossain Mondal.


C#
// C# code to implement the approach
using System;
class GFG {
 
  // Function to return maximum count
  public static int pick_max_elements(int pos, int sum,
                                      int n, int[] arr)
  {
 
    // Return if the end of the array
    // is reached
    if (pos == n)
      return 0;
 
    int taken = Int32.MinValue;
 
    // If we select element at index pos
    if (sum + arr[pos] >= 0)
      taken = 1
      + pick_max_elements(
      pos + 1, sum + arr[pos], n, arr);
 
    int not_taken
      = pick_max_elements(pos + 1, sum, n, arr);
 
    // Return the maximize steps taken
    return Math.Max(taken, not_taken);
  }
 
  // Driver code
  public static void Main(string[] args)
  {
    int[] arr = { 1, -4, -2, -3 };
    int N = arr.Length;
 
    // Function to pick maximum number
    // of elements
    Console.Write(pick_max_elements(0, 0, N, arr));
  }
}
 
// This code is contributed by ukasp.


Javascript


C++
// C++ code to implement the approach
 
#include 
using namespace std;
 
// Function to return max count
int pick_max_elements(int arr[], int n)
{
    int cnt = 0, sum = 0;
 
    // To store elements in sorted order
    multiset s;
 
    for (int i = 0; i < n; i++) {
        sum += arr[i];
 
        // An element added,
        // so increase the cnt
        cnt++;
        s.insert(arr[i]);
        if (sum < 0) {
            sum = sum - *s.begin();
 
            // To remove the
            // smallest element
            s.erase(s.begin());
 
            // Removed an element,
            // so decrease the cnt
            cnt--;
        }
    }
    return cnt;
}
 
// Driver code
int main()
{
    int arr[] = { 1, -4, -2, -3 };
 
    // Size of array
    int N = sizeof(arr) / sizeof(arr[0]);
 
    // Function to pick
    // maximum number of elements
    cout << pick_max_elements(arr, N);
    return 0;
}


输出
1

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

高效的方法:有效的方法是使用基于以下思想的多重集:

请按照下面给出的插图更好地理解。

插图:

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

  • i = 0 迭代到 N
    • 增加计数
    • 将当前元素添加到子集总和。
    • 将 arr[i] 插入集合中。
    • 如果总和变为负数,则从集合中减去最小值,并从集合中删除最小元素
    • 减少计数
  • 返回最终计数。

下面是上述方法的实现:

C++

// C++ code to implement the approach
 
#include 
using namespace std;
 
// Function to return max count
int pick_max_elements(int arr[], int n)
{
    int cnt = 0, sum = 0;
 
    // To store elements in sorted order
    multiset s;
 
    for (int i = 0; i < n; i++) {
        sum += arr[i];
 
        // An element added,
        // so increase the cnt
        cnt++;
        s.insert(arr[i]);
        if (sum < 0) {
            sum = sum - *s.begin();
 
            // To remove the
            // smallest element
            s.erase(s.begin());
 
            // Removed an element,
            // so decrease the cnt
            cnt--;
        }
    }
    return cnt;
}
 
// Driver code
int main()
{
    int arr[] = { 1, -4, -2, -3 };
 
    // Size of array
    int N = sizeof(arr) / sizeof(arr[0]);
 
    // Function to pick
    // maximum number of elements
    cout << pick_max_elements(arr, N);
    return 0;
}
输出
1

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