将序列分割成可形成非递减序列的片段的最小切割次数

时间:2015-11-28 15:26:53

标签: algorithm graph-theory set-theory

我有N个整数,例如3,1,4,5,2,8,7。可能有一些重复。我想将这个序列分成连续的子序列,这样我们就可以从它们形成非递减序列。如何计算最小数量的削减?对于上面提到的示例,答案是6,因为我们可以将此序列划分为{3},{1},{4,5},{2},{7},{8},然后形成{1,2 ,3,4,5,7,8}。最快的方法是什么?

有人知道如何解决它,假设某些数字可能相等吗?

2 个答案:

答案 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

63意味着切断序列[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