📌  相关文章
📜  最大子集和在范围 [L, R] 中的最大值和最小值之间存在差异

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

最大子集和在范围 [L, R] 中的最大值和最小值之间存在差异

给定一个由N个正整数组成的数组arr[]和一个范围[L, R] ,任务是找到最大子集和,使得子集的最大和最小元素之间的差位于给定范围内。

例子:

方法:在对给定数组进行排序后,可以借助二分搜索来解决给定的问题。以下是要遵循的步骤:

  • 以非递减顺序对给定数组进行排序。
  • 使用此处讨论的算法创建前缀和数组sum[]
  • 对于[0, N)范围内的所有i值,使用变量i遍历数组。
  • 对于每个i ,找到最大整数的索引j使得arr[j] <= arr[i] + R 。这可以使用 upper_bound函数来完成。
  • 维护一个变量ans ,它存储最大子集和。最初, ans = 0
  • 如果子数组 arr[i, j]形成有效子集,则将 ans 的值更新为ans的最大值子数组arr[i, j]的总和。
  • 存储在ans中的值是所需的答案。

下面是上述方法的实现:

CPP
// C++ program for the above approach
#include 
using namespace std;
 
// Function to find Maximum Subset Sum such
// that the difference between maximum and
// minimum elements lies in the range [L, R]
int maxSubsetSum(vector arr, int L, int R)
{
    int N = arr.size();
 
    // Sort the given array arr[] in
    // non-decreasing order
    sort(arr.begin(), arr.end());
 
    // Stores the sum of elements till
    // current index of the array arr[]
    int sum[N + 1] = {};
 
    // Stores the Maximum subset sum
    int ans = 0;
 
    // Create prefix sum array
    for (int i = 1; i <= N; i++) {
        sum[i] = sum[i - 1] + arr[i - 1];
    }
 
    // Iterate over all indices of array
    for (int i = 0; i < N; i++) {
 
        // Maximum possible value of
        // subset considering arr[i]
        // as the minimum element
        int val = arr[i] + R;
 
        // Calculate the position of the
        // largest element <= val
        auto ptr = upper_bound(
            arr.begin(), arr.end(), val);
        ptr--;
        int j = ptr - arr.begin();
 
        // If the difference between the
        // maximum and the minimum lies in
        // the range, update answer
        if ((arr[j] - arr[i] <= R)
            && (arr[j] - arr[i] >= L)) {
            ans = max(ans, sum[j + 1] - sum[i]);
        }
    }
 
    // Return Answer
    return ans;
}
 
// Driver Code
int main()
{
    vector arr{ 6, 5, 0, 9, 1 };
    int L = 0;
    int R = 3;
    cout << maxSubsetSum(arr, L, R);
 
    return 0;
}


Java
// Java program for the above approach
import java.util.*;
 
class GFG{
 
  static int upperBound(int[] a, int low, int high, int element){
    while(low < high){
      int middle = low + (high - low)/2;
      if(a[middle] > element)
        high = middle;
      else
        low = middle + 1;
    }
    return low;
  }
 
  // Function to find Maximum Subset Sum such
  // that the difference between maximum and
  // minimum elements lies in the range [L, R]
  static int maxSubsetSum(int[] arr, int L, int R)
  {
    int N = arr.length;
 
    // Sort the given array arr[] in
    // non-decreasing order
    Arrays.sort(arr);
 
    // Stores the sum of elements till
    // current index of the array arr[]
    int []sum  = new int[N + 1];
 
    // Stores the Maximum subset sum
    int ans = 0;
 
    // Create prefix sum array
    for (int i = 1; i <= N; i++) {
      sum[i] = sum[i - 1] + arr[i - 1];
    }
 
    // Iterate over all indices of array
    for (int i = 0; i < N; i++) {
 
      // Maximum possible value of
      // subset considering arr[i]
      // as the minimum element
      int val = arr[i] + R;
 
      // Calculate the position of the
      // largest element <= val
      int ptr = upperBound(arr, 0, N,val);
      ptr--;
      int j = ptr;
 
      // If the difference between the
      // maximum and the minimum lies in
      // the range, update answer
      if ((arr[j] - arr[i] <= R)
          && (arr[j] - arr[i] >= L)) {
        ans = Math.max(ans, sum[j + 1] - sum[i]);
      }
    }
 
    // Return Answer
    return ans;
  }
 
  // Driver Code
  public static void main(String[] args)
  {
    int[] arr = { 6, 5, 0, 9, 1 };
    int L = 0;
    int R = 3;
    System.out.print(maxSubsetSum(arr, L, R));
 
  }
}
 
// This code is contributed by umadevi9616


Python3
# Python Program to implement
# the above approach
from functools import cmp_to_key
 
def cmp_sort(a, b):
    return a - b
 
def InsertionIndex(nums, target, left):
    low = 0
    high = len(nums)
 
    while (low < high):
        mid = low + ((high - low) // 2)
 
        if (nums[mid] > target or (left and target == nums[mid])):
            high = mid
        else:
            low = mid + 1
 
    return low
 
def upper_bound(nums, target):
    targetRange = [-1, -1]
 
    leftIdx = InsertionIndex(nums, target, True)
 
    if (leftIdx == len(nums) or nums[leftIdx] != target):
        return targetRange
 
    targetRange[0] = leftIdx
    targetRange[1] = InsertionIndex(nums, target, False) - 1
 
    return targetRange
 
def maxSubsetSum(arr, L, R):
    N = len(arr)
 
    # Sort the given array arr[] in
    # non-decreasing order
    arr.sort(key = cmp_to_key(cmp_sort))
 
    # Stores the sum of elements till
    # current index of the array arr[]
    sum = [0 for i in range(N+1)]
 
    # Stores the Maximum subset sum
    ans = 0
 
    # Create prefix sum array
    for i in range(1,N+1):
        sum[i] = sum[i - 1] + arr[i - 1]
    # Iterate over all indices of array
    for i in range(N):
 
        # Maximum possible value of
        # subset considering arr[i]
        # as the minimum element
        val = arr[i] + R
 
        # Calculate the position of the
        # largest element <= val
        ptr = upper_bound(arr, val)
        j = ptr[1]
 
        # If the difference between the
        # maximum and the minimum lies in
        # the range, update answer
        if ((arr[j] - arr[i] <= R) and (arr[j] - arr[i] >= L)):
            ans = max(ans, sum[j + 1] - sum[i])
 
    # Return Answer
    return ans
 
# Driver Code
arr = [6, 5, 0, 9, 1]
L = 0
R = 3
print(maxSubsetSum(arr, L, R))
 
# This code is contributed by shinjanpatra


Javascript



输出:
15

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