查找给定数组的所有子区间可能的最大差值之和

时间:2018-03-13 18:32:41

标签: algorithm

我在设计算法时遇到了问题。问题是这应该在O(n)时间内执行。

这是作业: 有一个带有n个数字的未排序数组“a”。

mij=min{ai, ai+1, ..., aj}, Mij=max{ai, ai+1, ..., aj}

计算:

S=SUM[i=1,n] { SUM[j=i,n] { (Mij - mij) } }

我能够在O(nlogn)时间内解决这个问题。这是一项大学研究任务。我试过的一切表明这是不可能的。如果你能指出我找到解决方案的正确方向,我将非常感激。或者至少证明这是不可能的。

进一步解释:

给定ij,找到数组切片a [i:j]的最大和最小元素。减去那些以获得切片范围a[max]-a[min]

现在,为所有(i,j)添加所有切片的范围,使1 <= i <= j <= n。在 O(n)时间内完成。

1 个答案:

答案 0 :(得分:1)

这是非常直接的问题。 我将假设它是对象数组(如值对或元组)而不是数字。第一个值是数组中的索引,第二个值是值。

这里正确的问题是我们需要多少时间将每个数相乘并从总和中加/减它,即它是最大和最小元素的子序列数。 这个问题与寻找下一个最大元素(nge)有关,你可以看到here,只是为了解未来的问题。

我会用伪代码写它。

subsum (A):
    returnSum = 0
    //i am pushing object into the stack. Firt value is index in array, secong is value
    lastStackObject.push(-1, Integer.MAX_INT)
    for (int i=1; i<n; i++)
        next = stack.pop()
        stack.push(next)
        while (next.value < A[i].value)
            last = stack.pop()
            beforeLast = stack.peek()
            retrunSum = returnSum + last.value*(i-last.index)*(last.index-beforeLast.index)
        stack.push(A[i])

    while stack is not empty:
        last = stack.pop()
        beforeLast = stack.peek()
        retrunSum = returnSum + last.value*(A.length-last.index)*(last.index-beforeLast.index)

    return returnSum

sum(A)
    //first we calculate sum of maximum values in subarray, and then sum of minimum values. This is done by simply multiply each value in array by -1
    retrun subsum(A)+subsum(-1 for x in A.value)

此代码的时间复杂度为O(n)。

Peek函数只是读取堆栈中的下一个值而不会弹出它。