总和小于每个数组元素的最大子集
给定一个包含N个元素的数组arr[] ,任务是找到每个数组元素arr[i]的最大子集的大小,使得子集的总和小于该元素。
例子:
Input: arr[] = { 5, 2, 1, 1, 1, 6, 8}
Output: 3 1 0 0 0 4 4 +
Explanation:
For i = 0 -> subset = {1, 1, 1}, sum = 3. No other larger subset has sum less than 5.
For i = 1 -> subset = {1}. Sum = 1 which is less than arr[1] = 2
For i = 2 -> subset = {}. No element with value less than 1 present in array.
For i = 3 and i = 4 also subsets will have no element.
For i = 5 -> subset = {2, 1, 1, 1}, sum = 5 which is less than arr[5] = 6 and largest in size.
For i = 6 -> subset = {2, 1, 1, 1}, sum = 5 which is less than arr[6] = 8 and largest in size.
Input: arr[] = { 2, 1, 4, 5, 3, 2, 1 }
Output: 1 0 2 3 2 1 0
朴素方法:解决问题的最简单方法是形成每个arr[i]的所有子集,并在所有子集中找到总和小于该元素的最大子集。
时间复杂度: O(N*2 N )
辅助空间: O(2 N )
更好的方法:解决问题的更好方法是使用基于以下思想的贪婪方法。
Make a copy of the actual array and sort the duplicate increasingly. After that for each array element (arr[i]) traverse the duplicate array and find the maximum of how many elements from the start can be added to a subset such that the sum is less than arr[i].
请按照以下步骤解决问题:
- 制作数组的副本(例如v )。
- 按升序对副本进行排序。
- 从i = 0 到 N-1遍历数组:
- 对于从副本的开头遍历的每个元素,并且:
- 检查添加副本的当前元素是否使总和小于arr[i] 。
- 如果总和超过arr[i] ,则中断循环。
- 否则,遍历循环并增加子集的大小。
- 将子集大小添加到结果数组。
- 对于从副本的开头遍历的每个元素,并且:
- 返回结果数组。
下面是上述方法的实现。
C++
// C++ code to implement above approach
#include
using namespace std;
// Function to find out the largest subset
// for each array element
vector max_subset(int a[], int n)
{
// Making another copy of array
vector v, ans;
for (int i = 0; i < n; i++)
v.push_back(a[i]);
// Sorting the vector
sort(v.begin(), v.end());
// Iterating over every elements
// of the array
for (int i = 0; i < n; i++) {
// Finding the maximum number
// of elements whose sum
// is less than a[i]
int sum = 0, maxi = 0;
for (int j = 0; j < n; j++) {
sum += v[j];
if (sum >= a[i]) {
maxi = j;
break;
}
}
ans.push_back(maxi);
}
return ans;
}
// Driver code
int main()
{
int arr[] = { 5, 2, 1, 1, 1, 6, 8 };
int N = sizeof(arr) / sizeof(arr[0]);
// Function call
vector ans = max_subset(arr, N);
for (int x : ans)
cout << x << " ";
return 0;
}
Java
// Java implementation of above approach
import java.io.*;
import java.util.*;
class GFG {
// Function to find out the largest subset
// for each array element
static ArrayList max_subset(int[] a, int n)
{
// Making another copy of array
ArrayList v = new ArrayList();
ArrayList ans = new ArrayList();
for (int i = 0; i < n; i++)
v.add(a[i]);
// Sorting the vector
Collections.sort(v);
// Iterating over every elements
// of the array
for (int i = 0; i < n; i++) {
// Finding the maximum number
// of elements whose sum
// is less than a[i]
int sum = 0, maxi = 0;
for (int j = 0; j < n; j++) {
sum += (int)v.get(j);
if (sum >= a[i]) {
maxi = j;
break;
}
}
ans.add(maxi);
}
return ans;
}
// Driver Code
public static void main(String[] args)
{
int[] arr = { 5, 2, 1, 1, 1, 6, 8 };
int N = arr.length;
// Function call
ArrayList ans = max_subset(arr, N);
for(int x : ans)
System.out.print(x + " ");
}
}
// This code is contributed by sanjoy_62.
Python3
# Python3 code to implement the above approach
# function to find the largest subset for each
# array element
def max_subset(a, n):
# making a copy if a
v = a.copy()
ans = []
# sorting v
v.sort()
# iterating over a
for i in range(n):
# finding the max number of elements
# whose sum is less than a[i]
sums = 0
maxi = 0
for j in range(n):
sums += v[j]
if sums >= a[i]:
maxi = j
break
ans.append(maxi)
return ans
# Driver Code
arr = [5, 2, 1, 1, 1, 6, 8]
N = len(arr)
# Function call
ans = max_subset(arr, N)
print(" ".join(list(map(str, ans))))
# This code is contributed by phasing7.
C#
// C# code to implement above approach
using System;
using System.Collections;
class GFG {
// Function to find out the largest subset
// for each array element
static ArrayList max_subset(int[] a, int n)
{
// Making another copy of array
ArrayList v = new ArrayList();
ArrayList ans = new ArrayList();
for (int i = 0; i < n; i++)
v.Add(a[i]);
// Sorting the vector
v.Sort();
// Iterating over every elements
// of the array
for (int i = 0; i < n; i++) {
// Finding the maximum number
// of elements whose sum
// is less than a[i]
int sum = 0, maxi = 0;
for (int j = 0; j < n; j++) {
sum += (int)v[j];
if (sum >= a[i]) {
maxi = j;
break;
}
}
ans.Add(maxi);
}
return ans;
}
// Driver code
public static void Main()
{
int[] arr = { 5, 2, 1, 1, 1, 6, 8 };
int N = arr.Length;
// Function call
ArrayList ans = max_subset(arr, N);
foreach(int x in ans) Console.Write(x + " ");
}
}
// This code is contributed by Samim Hossain Mondal.
Javascript
C++
// C++ code to implement above approach
#include
using namespace std;
// Function to find the largest subset
// with sum less than arr[i]
vector max_subset(int a[], int n)
{
// Making another copy of array
vector v, ans;
for (int i = 0; i < n; i++)
v.push_back(a[i]);
// Sorting the vector
sort(v.begin(), v.end());
// Prefix sum array
int pref[n];
pref[0] = v[0];
for (int i = 1; i < n; i++)
pref[i] = pref[i - 1] + v[i];
// Iterating over every elements
// of the array
for (int i = 0; i < n; i++) {
// Using prefix array and
// lower_bound() function for
// finding the maximum number
// of elements
auto it
= lower_bound(pref,
pref + n, a[i]);
int maxi = it - pref;
ans.push_back(maxi);
}
return ans;
}
// Driver code
int main()
{
int arr[] = { 5, 2, 1, 1, 1, 6, 8 };
int N = sizeof(arr) / sizeof(arr[0]);
// Function call
vector ans = max_subset(arr, N);
for (int x : ans)
cout << x << " ";
return 0;
}
Python3
# Python3 code to implement the above approach
from bisect import bisect_left
# Function to find the largest subset
# with sum less than arr[i]
def max_subset(a, n):
# making another copy of the array
v = a.copy()
ans = []
# sorting v
v.sort()
# prefix sum array
pref = [v[0]]
for i in range(n - 1):
pref.append(pref[i] + v[i + 1])
# iterating over ever element
# of the array
for i in range(n):
# using prefix array and bisect_left() Function
# for finding the max number of elements
# bisect_left(pref, a[i]) returns the rightmost element
# greater than or equal to a[i]
it = bisect_left(pref, a[i])
maxi = it
ans.append(maxi)
return ans
# Driver Code
arr = [5, 2, 1, 1, 1, 6, 8]
N = len(arr)
print(" ".join(map(str, max_subset(arr, N))))
# This code is contributed by phasing17.
3 1 0 0 0 4 4
时间复杂度:O(N 2 )
辅助空间:O(N)
高效方法:高效方法与前一种方法类似,但它使用了这里提到的前缀和和下限的概念;
After sorting the duplicate array build a prefix sum array of the duplicate array.
For each element instead of iterating the duplicate array use lower bound in the prefix sum array to find the number of elements that can be included in a subset.
请按照以下步骤操作:
- 构建一个重复数组并对重复项进行排序(例如v )。
- 为v构建前缀数组。
- 在 arr[] 中从 i = 0 迭代到 N-1:
- 在前缀数组中使用下限并找出子集中可以包含多少个元素。
- 在结果数组中添加子集大小。
- 返回结果数组。
下面是上述方法的实现。
C++
// C++ code to implement above approach
#include
using namespace std;
// Function to find the largest subset
// with sum less than arr[i]
vector max_subset(int a[], int n)
{
// Making another copy of array
vector v, ans;
for (int i = 0; i < n; i++)
v.push_back(a[i]);
// Sorting the vector
sort(v.begin(), v.end());
// Prefix sum array
int pref[n];
pref[0] = v[0];
for (int i = 1; i < n; i++)
pref[i] = pref[i - 1] + v[i];
// Iterating over every elements
// of the array
for (int i = 0; i < n; i++) {
// Using prefix array and
// lower_bound() function for
// finding the maximum number
// of elements
auto it
= lower_bound(pref,
pref + n, a[i]);
int maxi = it - pref;
ans.push_back(maxi);
}
return ans;
}
// Driver code
int main()
{
int arr[] = { 5, 2, 1, 1, 1, 6, 8 };
int N = sizeof(arr) / sizeof(arr[0]);
// Function call
vector ans = max_subset(arr, N);
for (int x : ans)
cout << x << " ";
return 0;
}
Python3
# Python3 code to implement the above approach
from bisect import bisect_left
# Function to find the largest subset
# with sum less than arr[i]
def max_subset(a, n):
# making another copy of the array
v = a.copy()
ans = []
# sorting v
v.sort()
# prefix sum array
pref = [v[0]]
for i in range(n - 1):
pref.append(pref[i] + v[i + 1])
# iterating over ever element
# of the array
for i in range(n):
# using prefix array and bisect_left() Function
# for finding the max number of elements
# bisect_left(pref, a[i]) returns the rightmost element
# greater than or equal to a[i]
it = bisect_left(pref, a[i])
maxi = it
ans.append(maxi)
return ans
# Driver Code
arr = [5, 2, 1, 1, 1, 6, 8]
N = len(arr)
print(" ".join(map(str, max_subset(arr, N))))
# This code is contributed by phasing17.
3 1 0 0 0 4 4
时间复杂度: O(N * log(N))
辅助空间: O(N)