总和至少为 0 的 Array 的最大子集
给定一个包含N个整数的数组arr[] ,任务是找到总和至少为 0 的最大子集。
例子:
Input: arr[] = {5, -7, 0, -5, -3, -1}
Output: 4
Explanation: The largest subset that can be selected is {5, 0, -3, -1}. It has size 4
Input: arr[] = {1, -4, -2, -3}
Output: 1
Naive Approach:解决问题的基本思想是基于以下思想使用递归:
At every index, there are two choices, either select that element or not. If sum is becoming negative then don’t pick it otherwise pick it. And from every recursion return the size of the largest possible subset between the two choices.
请按照以下步骤操作:
- 使用递归函数,对于每个索引,有两种选择,要么选择该元素,要么不选择该元素。
- 避免选择该元素,其值使总和为负。
- 从两个选项中返回最大选取元素的计数。
- 所有这些中的最大值是所需的子集大小。
下面是上述方法的实现:
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)
高效的方法:有效的方法是使用基于以下思想的多重集:
Traverse from start of array and if at any index the sum till now becomes negative then erase the minimum element till current index from the subset. This will increase the subset sum.
To efficiently find the minimum multiset is used.
请按照下面给出的插图更好地理解。
插图:
Consider the array arr[] = {1, -4, -2, -3}
multiset
-> Insert arr[0] in s. s = {1}. sum = sum + arr[0] = 1
-> Insert arr[1] in s. s = { -4, 1 }. sum = sum + arr[1] = -3
-> Remove the smallest element (i.e. -4). sum = -3 – (-4) = 1.
-> Insert arr[2] in s. s = { -2, 1 }. sum = sum + arr[2] = -1
-> Remove the smallest element (i.e. -2). sum = -1 – (-2) = 1.
-> Insert arr[3] in s. s = { -3, 1 }. sum = sum + arr[1] = -2
-> Remove the smallest element (i.e. is -3). sum = -2 – (-3) = 1.
Total 1 element in the subset
请按照以下步骤解决此问题:
- 从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)