algorithm – 排序编号的最小特殊移动次数

给出数字列表

1 15 2 5 10

我需要获得

1 2 5 10 15

我能做的唯一操作是“在位置Y移动数字X”.

在上面的例子中,我只需要“在第5位移动数字15”.

我希望尽量减少操作次数,但鉴于可用的操作,我无法找到/记住经典算法.

一些背景:

>我正在与一个类似看板的服务的API进行交互.
>我有大约600张卡,我们的错误跟踪器上的一些操作可能意味着在看板中重新排序这600张卡(如果项目的优先级发生变化,多张卡可以同时移动)
>我可以在600次调用API中执行此操作,但我正在尝试尽可能减少该数量.

最佳答案 引理:您可以执行的对列表L(按递增顺序)排序的最小(删除元素,插入元素)对的数量为:

Smin(L) = |L| – |LIC(L)|

其中LIC(L)是最长的子序列.

因此,你必须:

>建立清单的LIC.
>删除不在其中的元素并将其插回适当的位置(使用二分查找).

证明:
通过归纳.

对于大小为1的列表,增长最长的子序列的长度为1!该列表已经排序,因此所需的(del,ins)对的数量是

|L| – |LIC(L)| = 1 – 1 = 0

现在让Ln成为长度为n,1≤n的列表.令Ln 1为通过在Ln的左侧添加元素en 1而获得的列表.
该元素可能会或可能不会影响最长增长子序列.让我们试着看看……

让in,1和in,2是LIC(Ln)(*)的两个第一个元素:

>如果en 1> in,2,然后LIC(Ln 1)= LIC(Ln)
>如果en1≤in,1,则LIC(Ln 1)= en 1 || LIC(LN)
>否则,LIC(Ln 1)= LIC(Ln) – in,1 en 1.我们保持LIC具有最高的第一元素.这是通过从LIC中删除1,并用en 1替换它来完成的.

在第一种情况下,我们删除en 1,因此我们得到Ln的排序.通过诱导假设,这需要n(缺失,插入)对.然后我们必须在适当的位置插入en 1.从而:

S(Ln+1)min = 1 + S(Ln)min
S(Ln+1)min = 1 + n – |LIC(Ln)|
S(Ln+1)min = |Ln+1| – |LIC(Ln+1|

在第二种情况下,我们忽略en 1.我们首先删除不在LIC(Ln)中的元素.必须再次插入这些元素!有

S(Ln)min = |Ln| – |LIC(Ln)|

这样的元素.

现在,我们只需要小心并按正确的顺序插入它们(相对于en 1).最后,它需要:

S(Ln+1)min = |Ln| – |LIC(Ln)|
S(Ln+1)min = |Ln| + 1 – (|LIC(Ln)| + 1)

因为我们有| LIC(Ln 1)| = | LIC(Ln)| 1和| Ln 1 | = | Ln | 1,我们到底有:

S(Ln+1)min = |Ln+1| – |LIC(Ln+1)|

最后一种情况可以通过考虑通过从Ln 1中移除1得到的列表L’n来证明.在那种情况下LIC(L’n)= LIC(Ln 1)并且因此:

|LIC(L’n)| = |LIC(Ln)| (1)

从那里,我们可以对L’n进行排序(这需要| L’n | – | LIC(L’n |由归纳假设.先前的等式(1)导致结果.

(*):如果LIC(Ln)< 2,然后在,2不存在.只需忽略与它的比较.在这种情况下,只有案例2和案例3适用……结果仍然有效

点赞