我在设计算法时遇到了问题。问题是这应该在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)时间内解决这个问题。这是一项大学研究任务。我试过的一切表明这是不可能的。如果你能指出我找到解决方案的正确方向,我将非常感激。或者至少证明这是不可能的。
进一步解释:
给定i
和j
,找到数组切片a [i:j]的最大和最小元素。减去那些以获得切片范围a[max]-a[min]
。
现在,为所有(i,j)添加所有切片的范围,使1 <= i <= j <= n
。在 O(n)时间内完成。
答案 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函数只是读取堆栈中的下一个值而不会弹出它。