我们获得了a
个n
个数字的序列。序列a
的减少定义为将元素a[i]
和a[i+1]
替换为max(a[i],a[i+1])
。
每个减少操作的成本定义为max(a[i],a[i+1])
。减少n-1
后,将获得一长度1
的序列。
现在我们的目标是打印给定序列a
的最佳减少成本,使得长度为1的结果序列具有最低成本。
e.g:
1
2
3
Output :
5
O(N ^ 2)解决方案是微不足道的。有什么想法吗?
EDIT1: 人们在询问我的想法,所以我的想法是成对地遍历序列,并且每对检查成本,最后以最低的成本减少对。
1 2 3
2 3 <=== Cost is 2
将上述序列减少到
2 3
现在再次遍历序列,我们得到成本为3
2 3
3 <=== Cost is 3
因此总成本为2 + 3 = 5
以上算法为O(N ^ 2)。这就是为什么我要求更优化的想法。
答案 0 :(得分:2)
O(n)
解决方案:
<强>高级别强>
基本思想是重复合并任何小于其邻居e
和ns
的元素nl
及其最小邻居ns
。这会产生最小的成本,因为合并的成本和结果都是max(a[i],a[i+1])
,这意味着没有合并可以使元素比当前小,因此e
最便宜的合并是{{1并且,该合并不能增加任何其他可能的合并的成本。
这可以通过一次通过算法来完成,方法是按顺序保持数组中的元素堆栈。我们将当前元素与其邻居(一个是堆栈的顶部)进行比较,并执行适当的合并,直到我们完成。
<强>的伪代码:强>
ns
Java代码:
stack = empty
for pos = 0 to length
// stack.top > arr[pos] is implicitly true because of the previous iteration of the loop
if stack.top > arr[pos] > arr[pos+1]
stack.push(arr[pos])
else if stack.top > arr[pos+1] > arr[pos]
merge(arr[pos], arr[pos+1])
else while arr[pos+1] > stack.top > arr[pos]
merge(arr[pos], stack.pop)
答案 1 :(得分:0)
如果你的意思是减少“计算成本”的“成本”,即操作花费时间max(a[i],a[i+1])
或者只是你想要计算的东西,我很困惑。如果是后者,则以下算法优于O(n ^ 2):
b[i]
s.t. a[b[i]]
是排序列表:如果可以使用RADIX排序,则为O(n),否则为O(n log n)。i
开始:如果左/右低于i,则执行减少:每个项目为O(1),更新列表为2,O(n)总的来说。我不知道这是否是最佳解决方案,但是对于整数而言是O(n),对于整数而言是O(n log n),否则就是。
编辑:意识到删除预先计算步骤使其更加简单
答案 2 :(得分:0)
贪婪的方法确实有效。
您可以随时使用较小的邻居减少最小数量。
证明:我们必须在某个时候减少最小数量。邻居的任何减少都会使邻居的值至少相同(可能)更大,因此减少最小元素a [i]的操作将始终具有成本c> = min(a [i-1],a [i + 1])
现在我们需要
我会选择2个RMQ。将操作2作为二分查找。这给了我们O(N * log ^ 2(N))
编辑:第一个RMQ - 值。当你删除一个元素时,会有一些很大的价值
第二个RMQ - “存在”。 0或1(值存在/不存在)。要查找[i]的[例如]左邻居,您需要找到l
最大的sum[l,i-1] = 1
。
答案 3 :(得分:0)
如果您不认为对列表进行排序是作弊的,那么请在n log n
时间内进行,然后递归合并前两个条目。在这种情况下,总成本将是条目总和减去最小条目。这是最佳的,因为
n-1
条目的总和(允许重复)i
最小条目在费用函数中最多可出现i-1
次即使列表未排序,同样的基本思想仍然有效。最佳解决方案是将最小元素与其最小邻居合并。要确保这是最佳的,请注意
n-1
条目的总和(允许重复)a_i
最多可在费用函数中显示j-1
次,其中j
是包含a_i
的最长连续子序列的长度,a_i
}是子序列的最大元素在最坏的情况下,序列正在减少,时间为O(n^2)
。