Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/363.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 执行所有M操作将导致数组中的最大元素_Java_Arrays_Algorithm_Dynamic Programming - Fatal编程技术网

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());