最大子集和在范围 [L, R] 中的最大值和最小值之间存在差异
给定一个由N个正整数组成的数组arr[]和一个范围[L, R] ,任务是找到最大子集和,使得子集的最大和最小元素之间的差位于给定范围内。
例子:
Input: arr[] = {6, 5, 0, 9, 1}, L = 0, R = 3
Output: 15
Explanation: The subset {6, 9} of the given array has the difference between maximum and minimum elements as 3 which lies in the given range [0, 3] and the sum of the elements as 15 which is the maximum possible.
Input: arr[] = {5, 10, 15, 20, 25}, L = 1, R = 2
Output: 0
Explanation: There exist no valid subsets.
方法:在对给定数组进行排序后,可以借助二分搜索来解决给定的问题。以下是要遵循的步骤:
- 以非递减顺序对给定数组进行排序。
- 使用此处讨论的算法创建前缀和数组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)