求给定数组的连续子集的最大可能差之和。
我们得到一个由n个非负整数(允许重复元素)组成的数组arr[],求出给定数组中相邻子集的最大差之和。
假设max(s)表示任何子集's'中的最大值,而min(s)表示集合's'中的最小值。我们需要为所有可能的子集找到max(s)-min(s)的总和。
Input : arr[] = {1, 2, 3}
Output : result = 4
解释:
All possible subset and for each subset s,
max(s)-min(s) are as :
SUBSET | max(s) | min(s) | max(s)-min(s)
{1, 2} | 2 | 1 | 1
{2, 3} | 3 | 2 | 1
{1, 2, 3} | 3 | 1 | 2
Total Difference sum = 4
Note : max(s) - min(s) for all subset with
single element must be zero.
约束条件:
Array size can be from 1 to 10 power 5, also each element in array can be from 1 to 10 power 5.
这是从此处获取的代码,但此代码检查所有可能的子集,而不是连续的子集:
public static int MOD = 1000000007;
// function for sum of max min difference
public static long maxMin (int arr[], int n)
{
// sort all numbers
Arrays.sort(arr);
// iterate over array and with help of
// horner's rule calc max_sum and min_sum
long min_sum = 0, max_sum = 0;
for (int i = 0; i < n; i++)
{
max_sum = 2 * max_sum + arr[n - 1 - i];
max_sum %= MOD;
min_sum = 2 * min_sum + arr[i];
min_sum %= MOD;
}
return (max_sum - min_sum + MOD)%MOD;
}
那么如何只得到连续的子集并以更低的时间复杂度解决这个问题。
您可以使用流来实现这一点:
public static int difference(int[] arr) {
int size = arr.length;
return IntStream.range(0, size)
.flatMap(i -> IntStream.range(i + 1, size)
.mapToObj(j -> Arrays.stream(arr, i, j + 1).summaryStatistics())
.mapToInt(stat -> stat.getMax() - stat.getMin()))
.sum();
}
或者,正如@kcsquare所注意到的,您可以使用2个stream
,一个用于最大和,另一个用于最小和,并减去它们。这种方法还避免了不必要的装箱
和解箱
。
public static int difference2(int[] arr) {
int size = arr.length;
int max = IntStream.range(0, size)
.flatMap(i -> IntStream.range(i + 1, size)
.map(j -> Arrays.stream(arr, i, j + 1).max().getAsInt()))
.sum();
int min = IntStream.range(0, size)
.flatMap(i -> IntStream.range(i + 1, size)
.map(j -> Arrays.stream(arr, i, j + 1).min().getAsInt()))
.sum();
return max - min;
}
让我们使用归纳法。
int a[] = {1, 2, 3};
long sum = 0;
for (int i = 1; i < a.length; i++) {
int min = a[i];
int max = a[i];
for (int j = i - 1; j >= 0; j--) {
int current = a[j];
if (current < min) min = current;
if (current > max) max = current;
sum += max - min;
}
}
System.out.println("Sum = " + sum);
您可以在时间和空间中执行此操作。
该技术是对所有最近的较小值使用该算法。首先,将问题分为两部分:
这两个问题的解决方案是相同的,除了用“大于”交换所有出现的“小于”,所以我只描述最小值的情况。
对于数组中的每个元素,您可以问:“有多少子数组的最小元素是?”为了处理重复项,假设我们总是将子数组中最小元素最右边的匹配项作为“代表”元素。
这个问题转化为:在看到一个严格小于A[i]的元素之前,我们可以走到A[i]的左边多远,在看到一个小到A[i]的元素之前,我们可以走到A[i]的右边多远。将这两个距离相乘,以获得子阵列中所有可能的左endpoint和右endpoint选择,这些子阵列的最小元素为A[i]。我们可以使用“所有最近的较小值”算法直接找到这两个值,然后像这样解决其余问题(伪代码):
1. For each position i in the array A, let previous_smaller[i]
be the largest index j such that A[j] < A[i] and 0 <= j < i,
or -1 if there is no such index.
2. For each position i in the array A, let next_smaller_or_equal[i]
be the smallest index j such that A[j] <= A[i] and i < j < n,
or n if there is no such index.
3. Return the sum over all i, 0 <= i < n, of
(A[i] *
(next_smaller_or_equal[i] - i) *
(i - previous_smaller[i]))
例如,在这个问题的答案中有几个最接近的较小值的实现,在维基百科的文章中有伪代码。要查找“下一个较小的值”而不是“前一个较小的值”,只需在一个反向数组上运行该算法(或者只需按反向顺序遍历a,从a[n-1]向下遍历到a[0])。
整个算法的示例实现(Python):
def max_difference_sum(A: List[int]) -> int:
"""Given an array of integers A, compute the
sum over all subarrays B of max(B) - min(B)
by using nearest smaller values"""
n = len(A)
# Convention to take the rightmost min or max in each subarray.
previous_smaller = list(range(n))
next_smaller_or_equal = list(range(n))
previous_larger = list(range(n))
next_larger_or_equal = list(range(n))
# Compute the previous larger and smaller in a single loop.
for i in range(n):
j = i - 1
while j >= 0 and A[j] >= A[i]:
j = previous_smaller[j]
previous_smaller[i] = j
j = i - 1
while j >= 0 and A[j] <= A[i]:
j = previous_larger[j]
previous_larger[i] = j
for i in reversed(range(n)):
j = i + 1
while j < n and A[j] > A[i]:
j = next_smaller_or_equal[j]
next_smaller_or_equal[i] = j
j = i + 1
while j < n and A[j] < A[i]:
j = next_larger_or_equal[j]
next_larger_or_equal[i] = j
max_sums = sum(A[i]
* (next_larger_or_equal[i] - i)
* (i - previous_larger[i])
for i in range(n))
min_sums = sum(A[i]
* (next_smaller_or_equal[i] - i)
* (i - previous_smaller[i])
for i in range(n))
return max_sums - min_sums
您将获得一个包含n个元素的数组:<代码>d[0],d[1]。。。,d【n-1】。计算所有相邻子数组的最大差值之和。 形式上:S=sum{max{d[l,..., r]}-min{d[l,..., r}},Δ0 输入: 输出: 解释: l=0;r=1;数组:[1,3]和=最大值([1,3])-最小值([1,3])=3-1=2 l=0;r=2;数组:[1,3,2]和=最大值([1,3,2])-最小值(
给定一组元素,如何在此列表的所有子集中找到MAX和MIN之间的差异。 例如: 集合=1 2 3
我一直在练习算法问题,我遇到了这个问题。 给定一个数组(+VE和-VE),我必须找到一个连续的子数组,这样,和可以被任意数K整除,并且该子数组可能是最大和。对于 和,可被k整除的最大和子数组是 ,目前我所能想到的是,每个元素都有两种可能,要么包含在目标子数组中,要么不包含在目标子数组中。但这将是一个指数算法。 编辑:是否有可能在线性时间内解决这个问题。请帮忙
我想从数组的一部分找到最大值和最小值。我知道我可以通过复制数组将所需的数组部分复制到另一个数组中,但只是想知道是否可以不复制数组,因为我必须为不同的子数组进行循环 例如: 现在我想从1到4找到子数组的最小/最大值(如果可能,不复制子数组)
假设数组是,现在获取此数组的所有子数组。对于每个子数组,在该子数组中找到最小值,也找到该子数组中的项目之和。最后添加所有这些值。输入无法按我想要的所有可能的子数组进行排序。 例子: 可能的子阵列包括: 最后,将所有这些值相加,得到结果=1 3 6 4 10 9=33。 约束:数组元素的范围从1到1000\u 000\u 000。数组大小从1到100\u 000。将输出作为模块7 1000\u 00
我正在组装一个java小程序,使任务在工作中更快、更高效。 用户定义项目列表需要拆分成的三个组的大小。列表中的每个项目根据它被放入三个组中的哪个组具有不同的值。小程序需要显示哪个组合的总价值最高。 示例:带有列的二维整数数组;项目编号、第1组中的值、第2组中的值和第3组中的值。 这样,用户定义组1有3个插槽,组2有3个插槽,组3有2个插槽。 小程序应不按特定顺序显示以下解决方案 我可以管理一种效率