使用N
元素数组初始化为0
。我们得到一系列M
种类的操作(p; q; r)。操作(p; q; r)表示应将整数r添加到所有数组元素A[p];A[p + 1]; : : : ;A[q]
。您将输出执行所有M
操作所产生的数组中的最大元素。有一个天真的解决方案,只需执行所有操作,然后返回最大值,这需要O(MN)
时间。我们正在寻找更有效的算法。
我正在寻找动态编程解决方案。你们有什么想法吗?
答案 0 :(得分:3)
这可以在O(M + N)
中解决,如下所述。首先,像这样建模你的Operation
:
class Operation {
final int p;
final int q;
final int r;
Operation(int p, int q, int r) {
this.p = p;
this.q = q;
this.r = r;
}
}
然后,创建一个数组,您可以在位置+op.r
添加op.p
,在-op.r
位置添加op.q + 1
包含上限(或op.q
用于包含上限边界)。这是M
的循环:
int[] array = new int[10];
Operation[] ops = {
new Operation(1, 7, 2),
new Operation(2, 5, 3),
new Operation(1, 3, 1)
};
for (Operation op : ops) {
int lo = op.p;
int hi = op.q + 1;
if (lo >= 0)
array[lo] = array[lo] + op.r;
if (hi < array.length)
array[hi] = array[hi] - op.r;
}
最后,遍历大小为N
的数组,并通过累计每个先前注册的+/- op.r
int maxIndex = Integer.MIN_VALUE;
int maxR = Integer.MIN_VALUE;
int r = 0;
for (int i = 0; i < array.length; i++) {
r = r + array[i];
System.out.println(i + ":" + r);
if (r > maxR) {
maxIndex = i;
maxR = r;
}
}
System.out.println("---");
System.out.println(maxIndex + ":" + maxR);
我的例子产生:
0:0
1:3
2:6
3:6
4:5
5:5
6:2
7:2
8:0
9:0
---
2:6
如果您拥有大量核心,则可以使用Java 8 API并行化以前的算法:
// Finally a use-case for this weird new Java 8 function!
Arrays.parallelPrefix(array, Integer::sum);
System.out.println(Arrays.stream(array).parallel().max());
对于大量N
和足够数量的核心,这可能比以前的顺序解决方案更快。
答案 1 :(得分:2)
使用正确的数据结构,您可以优化天真的解决方案以及时运行O(m log n + n log n)。具体来说,如果不是使用原始数组而是使用binary indexed tree (Fenwick tree),则可以在时间O(log n)中将位置p和q之间的数组中的所有元素添加到r中。您还可以在结尾查询每个元素的时间值O(log n),因此总运行时间将为O(m log n + n log n),明显快于您最初的运行时间。
有可能比这更好。如果我想到什么,我会告诉你的!
答案 2 :(得分:0)
你可能会让你成为分段树。这将占用O(n)空间并将在O(log n)时间内获得查询并在O(log n)中更新。因此,如果对N个元素有M个查询,则可以在O(M(log N))时间内完成。
答案 3 :(得分:0)
您无需在所有索引处计算总和。有效解决方案的简单想法是,记录每个操作的开始和结束以及为该操作添加的整数r
。
而不是寻求复杂的数据结构,简单的解决方案是 -
假设arr
是初始化为零的N
整数数组。对于每个操作(p; q; r)
更新索引p & q
,其中arr[p]=arr[p]+r
和arr[q+1]=arr[q+1]-r
除了最后一个索引。 arr
中的某些数字为-ve
,有些+ve
..
最后一步是从第一个索引到最后一个索引进行迭代,将每个索引的数字添加到current_sum
。此处current_sum
始终大于零,因为p<q
,因此r
会在减去之前添加到arr
。如果max_sum
大于current_sum
,请更新max_sum
。 {{1}}是执行所有M操作所产生的数组中的最大元素。