📌  相关文章
📜  总和小于每个数组元素的最大子集

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

总和小于每个数组元素的最大子集

给定一个包含N个元素的数组arr[] ,任务是找到每个数组元素arr[i]的最大子集的大小,使得子集的总和小于该元素。

例子:

朴素方法:解决问题的最简单方法是形成每个arr[i]的所有子集,并在所有子集中找到总和小于该元素的最大子集。

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

更好的方法:解决问题的更好方法是使用基于以下思想的贪婪方法

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

  • 制作数组的副本(例如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)

高效方法:高效方法与前一种方法类似,但它使用了这里提到的前缀和下限的概念;

请按照以下步骤操作:

  • 构建一个重复数组并对重复项进行排序(例如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)