Java 执行所有M操作将导致数组中的最大元素
使用初始化为Java 执行所有M操作将导致数组中的最大元素,java,arrays,algorithm,dynamic-programming,Java,Arrays,Algorithm,Dynamic Programming,使用初始化为0的N元素数组。我们得到了排序(p;q;r)的M操作序列。运算(p;q;r)表示整数r应添加到所有数组元素A[p];A[p+1];:;A[q]。您要输出数组中因执行所有M操作而产生的最大元素。有一种简单的解决方案,只需执行所有操作,然后返回最大值,这需要O(MN)时间。我们正在寻找一种更有效的算法 我正在寻找一个动态规划解决方案。你们有什么想法吗?使用正确的数据结构,您可以优化原始解决方案以在时间O(m log n+n log n)内运行。具体来说,如果不使用原始数组而使用a,则可以
0
的N
元素数组。我们得到了排序(p;q;r)的M
操作序列。运算(p;q;r)表示整数r应添加到所有数组元素A[p];A[p+1];:;A[q]
。您要输出数组中因执行所有M
操作而产生的最大元素。有一种简单的解决方案,只需执行所有操作,然后返回最大值,这需要O(MN)
时间。我们正在寻找一种更有效的算法
我正在寻找一个动态规划解决方案。你们有什么想法吗?使用正确的数据结构,您可以优化原始解决方案以在时间O(m log n+n log n)内运行。具体来说,如果不使用原始数组而使用a,则可以在时间O(logn)中将r添加到位置p和q(包括)之间的数组中的所有元素。您还可以在最后的时间O(logn)中查询每个元素的值,因此总运行时间将是O(mlogn+nlogn),大大快于最初的运行时间
也许可以做得比这更好。如果我有什么想法,我会告诉你的 您可能会使用段树。这将占用O(n)空间,并且将在O(logn)时间内获取查询并在O(logn)时间内更新。因此,如果在N个元素上有M个查询,您可以在O(M(logn))时间内完成。这可以在
O(M+N)
中解决,如下所示。首先,将您的操作建模如下:
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;
}
我的例子是:
0:0
1:3
2:6
3:6
4:5
5:5
6:2
7:2
8:0
9:0
---
2:6
Java8并行版本
如果您有大量内核,可以使用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
和足够数量的内核,这可能比以前的顺序解决方案快。您不需要计算所有索引的总和。高效解决方案的简单思想是,记录每个操作的开始和结束,并为该操作添加整数r
简单的解决方案是-
假设arr
是初始化为零的N
整数数组。对于每个操作(p;q;r)
使用arr[p]=arr[p]+r
和arr[q+1]=arr[q+1]-r
更新索引。arr
中的一些数字是-ve
和一些+ve
最后一步是从第一个索引迭代到最后一个索引,将每个索引处的数字添加到current\u sum
。这里的当前值总和将始终大于零,因为p结果必须是[0,3,6,6,5,5,2,2,0,0]
因为q
是包容性的。@saka1029:好的,我更改了答案以产生您期望的结果op.q==9
@LukasEder非常感谢:)会对实际解决方案实现非常好奇:)您确定复杂性正确吗?我认为当并行运行时,事情会少于O(N)
。它肯定比我的解决方案要好,它是在线性时间内运行的。
// Finally a use-case for this weird new Java 8 function!
Arrays.parallelPrefix(array, Integer::sum);
System.out.println(Arrays.stream(array).parallel().max());