执行所有M操作所产生的数组中的最大元素

时间:2016-03-10 23:09:06

标签: java arrays algorithm dynamic-programming

使用N元素数组初始化为0。我们得到一系列M种类的操作(p; q; r)。操作(p; q; r)表示应将整数r添加到所有数组元素A[p];A[p + 1]; : : : ;A[q]。您将输出执行所有M操作所产生的数组中的最大元素。有一个天真的解决方案,只需执行所有操作,然后返回最大值,这需要O(MN)时间。我们正在寻找更有效的算法。

我正在寻找动态编程解决方案。你们有什么想法吗?

4 个答案:

答案 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并行版

如果您拥有大量核心,则可以使用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]+rarr[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操作所产生的数组中的最大元素。