我们有n张牌,每张牌的编号从1到n。
随机洗牌。
我们只允许操作MoveCard(n),它将值为n的卡移动到堆的顶部。
我们需要用最少数量的MoveCard操作对这堆卡片进行排序。
我能想到的天真的方法是从MoveCard(n),MoveCard(n-1),MoveCard(n-2)...... MoveCard(1)开始。
这种方法将解决n个MoveCard操作中的问题。
但我们能否优化它。
例如,如果输入如下:3 1 4 2
根据我的方法:
4 3 1 2
3 4 1 2
2 3 4 1
1 2 3 4
MoveCard操作是4。
但我们可以用最少的动作来解决这个问题:
优化的解决方案是:
3 1 4 2
2 3 1 4
1 2 3 4
MoveCard操作是2。
从上面的优化解决方案中,我感觉以下方法将解决问题。
我们总是选择要移动的元素,它在顶部和底部给出已排序的元素,条件是从开始处排序的子数组中的最大元素应小于从底部开始的已排序子数组的最小元素
在这种情况下:
3 1 4 2
移动2我们得到2 3 1 4 {2,3从开始排序,4排序从底部}
现在我们选择1来提供完整的排序数组。 1 2 3 4。
答案 0 :(得分:1)
一种简单的方法是以相反的顺序查看数字。如果前两个不按顺序,则移动较低的一个。如果 按顺序排列,请查找下一个。找到一个不按顺序的,然后按顺序移动那个,然后按照它下面的每个其他卡。
基本上,找n
。如果n-1
在数组中 n
之后,请将n-1
移到前面。 n--
,然后重复。
例如:
2 4 3 1 // 3 comes after 4, so move 3
3 2 4 1 // move 2
2 3 4 1 // move 1
1 2 3 4 // done after 3 moves
3 1 4 2 // 3 comes -before- 4, so leave it alone. 2 comes after 3, move it
2 3 1 4 // move 1
1 2 3 4 // done after 2 moves
它最终与天真的方法相同,但仅从“最佳”开始开始。你并不总是需要移动顶牌。
最坏情况时间复杂度为O(n ^ 2),原因很简单,因为您必须对每个数字进行无序搜索。我不能证明这是最好的复杂性,但它肯定是最简单,最清晰的方法。
移动的最差案例数为n-1
,因为您始终可以单独留下n
卡。
现在,如果你只想知道你需要多少次移动,而不是实际排序,你可以在第一步时停下来。例如,如果您必须移动3
,因为它位于4
之后,那么您将需要3
次移动。您可以看到这一点,因为如果前面有3
,那么始终必须将其下方的每张卡片都移到前面。