理论上可以通过仅移动尚未按排序顺序排列的元素,在length(array) - length(longestIncreasingSubsequence(array))
移动中对数组进行排序。
如果允许的唯一操作是就地移动,通过从索引A中删除一个元素并将其重新插入索引B,一次一个元素,您将如何生成正确的移动以结束排序的数组?同样,应该需要length(array) - length(longestIncreasingSubsequence(array))
次移动。
例如,这是一个数组:
[ 1, 8, 5, 2, 4, 6, 3, 9, 7, 10 ]
增长最长的子序列是:
[ 1, 2, 4, 6, 7, 10 ]
这些元素的索引是:
[ 0, 3, 4, 5, 8, 9 ]
因此,我们需要移动的指数是:
[ 1, 2, 6, 7]
因为这些索引尚未按排序顺序排列。
为了得到排序数组,这4个元素的最终索引是:
[ 7, 4, 2, 8]
因此,我们需要同时将索引1移动到索引7,将索引2移动到索引4,将索引6移动到索引2,将索引7移动到索引8.问题是当移动元素时,其他元素被移位使后来的移动操作无效。我已经尝试过转换这些索引,但到目前为止还没有提出正确的移动列表。有什么想法吗?
希望我已经很好地解释了这个问题。请提问,我会澄清。谢谢!
答案 0 :(得分:5)
您的问题是源位置以先前的顺序表示,而目标位置是最终的顺序。当您执行1-> 7时,您还不知道先前顺序中的7。您需要对所有动作进行调整。
最初的举动是:
from: [ 1, 2, 6, 7]
to: [ 7, 4, 2, 8]
第1步
让我们首先转换位置,好像我们首先删除所有元素,然后将元素插入新位置。对于from
位置,从左侧开始:从1档位(2,6,7)向下移动到(1,5,6)。在1处移除再次将(5,6)向下移动到(4,5)。在5档移除5向下移动到4.对于from
中的每个位置,必须递减具有更大或相等索引的所有后续位置。我们得到:
from: [ 1, 1, 4, 4]
对于to
职位,从最后开始:职位8是正确的。位置2也是正确的,但这意味着先前(7,4)在插入时实际上是(6,3)。所以我们调整它们。类似地,在3处插入意味着先前位置6为5。
因此,对于to
数组,我们从最后开始,对于每个位置,我们递减所有具有较大索引的先前位置。 to
数组变为:
to: [ 5, 3, 2, 8]
第2步
我们所拥有的是4次移除的正确位置,然后是4次插入。现在我们想要删除删除和插入。
必须在(1,1,4)的删除之前进行5的插入。 5大于这些中的任何一个,因此它不会影响位置(1,1,4),但是5会受到影响,因为3个删除是在插入点的左侧完成的。 5变为8。
3处的插入必须在(4,4)处的移除之前进行。由于3小于4,因此位置3不受删除的影响,但删除必须增加到位置(5,5)。
2点的插入在5点的最后一次删除之前(是4)。它较小,因此将5调整为6。
第2步的一般方法:
for i = 0 to size-1
for j = size-1 to i+1
if from[j] < to[i] then increment to[i]
else increment from[j]
我们应该得到数组:
from: [ 1, 1, 5, 6]
to: [ 8, 3, 2, 8]
这些是在移动时使用正确位置执行的最终动作。移动可以从左到右读取:从1处移除,在8处插入。在1处移除,在3处插入3.在5处移除,在2处插入2.在6处移除,在8处插入。