我有N个整数,例如3,1,4,5,2,8,7。可能有一些重复。我想将这个序列分成连续的子序列,这样我们就可以从它们形成非递减序列。如何计算最小数量的削减?对于上面提到的示例,答案是6,因为我们可以将此序列划分为{3},{1},{4,5},{2},{7},{8},然后形成{1,2 ,3,4,5,7,8}。最快的方法是什么?
有人知道如何解决它,假设某些数字可能相等吗?
答案 0 :(得分:2)
我会在值减少的点处将数组切割成非递减段,然后将这些段用作(单个)合并阶段的输入 - 如在排序合并中 - 在可能的情况下保持相同的段在关系的情况下。当您必须从一个段切换到另一个段时,为剪切创建其他位置。
输出已排序,因此可以产生足够的切割来完成工作。在序列减少的点处或在必须创建间隙的点处产生剪切,因为原始序列跳过其他地方存在的数字 - 因此没有所有这些剪切的序列可以重新排列为排序顺序。
合并开销的最坏情况是初始序列正在减少。如果你使用堆来跟踪接下来要选择的序列,那么这会变成带有成本n log n的heapsort。通过从堆中提取相同值的所有匹配来处理绑定,然后才决定要做什么。
答案 1 :(得分:1)
如果列表不包含重复项,则此方法有效。也许这些可以先得到有效照顾。
我们可以使用Fenwick树计算O(n * log n)
时间和O(n)
空间中的置换反演向量。具有相同数字的矢量的连续段可以表示不需要切割的部分。不幸的是,他们也可以返回误报,例如,
Array: {8,1,4,5,7,6,3}
Vector: 0,1,1,1,1,2,5
6
和3
意味着切断序列[1,4,5,7]
。为了解决这个问题,我们采用第二个反演向量来表示每个元素后面的较小元素的数量。不需要切割两个向量中平行的连续段:
Array: {8,1,4,5,7,6,3,0}
Vector: 0,1,1,1,1,2,5,7 // # larger preceding
Vector: 7,1,2,2,3,2,1,0 // # smaller following
|---| // not cut
Array: {3,1,4,5,2,8,7}
Vectors: 0,1,0,0,3,0,1
2,0,1,1,0,1,0
|---| // not cut
Array: {3,1,2,4}
Vectors: 0,1,1,0
2,0,0,0
|---| // not cut