按限制排序整数

时间:2012-04-10 03:24:53

标签: algorithm sorting time-complexity

如果我们有一个整数数组,那么如果每步的唯一允许操作是:将元素移动到极值,我们如何确定排序它们所需的最小步骤(按升序排列)? 例如,如果我们有

7 8 9 11 1 10

然后在第一步中可以将11移动到右端,在第二步中移动1到左端以获得1 7 8 9 10 11。因此总步数= 2 可以在这里应用冒泡排序吗?但最糟糕的情况是O(n ^ 2)。那么我们怎样才能更有效率地做到? 谢谢。

4 个答案:

答案 0 :(得分:2)

这是一个需要O(n log n)时间,O(n)辅助空间以及n个MoveToFront操作的解决方案。

给定输入数组A,使用值/索引对创建第二个数组B,如此......

7 8 9 11 1 10  ->  (7 0) (8 1) (9 2) (11 3) (1 4) (10 5)
[this step takes O(n) time and O(n) space]

然后按每对价值的降序排序B ......

(7 0) (8 1) (9 2) (11 3) (1 4) (10 5) -> (11 3) (10 5) (9 2) (8 1) (7 0) (1 4)
[this step takes O(n log n) time]

准备二元搜索树,T。

现在,对于B中的每个元素,请执行以下操作...

Let I be the index of this element.
Let V be the sum of I and the number of elements in T that are greater than I.
Do a MoveToFront operation on the Vth element of A.
Add I to T.
[Both of the operations on T take O(log n) time]

这个算法适用于您的示例数组

(11 3)
    I := 3
    V := 3 + 0 = 3
    MoveToFront(3): 7 8 9 11 1 10  ->  11 7 8 9 1 10
    T: ()  ->  (3)

(10 5)
    I := 5
    V := 5 + 0 = 5
    MoveToFront(5): 11 7 8 9 1 10  ->  10 11 7 8 9 1
    T: (3)  ->  (3 5)

(9 2)
    I := 2
    V := 2 + 2 = 4
    MoveToFront(4): 10 11 7 8 9 1  ->  9 10 11 7 8 1
    T: (3 5)  ->  (2 3 5)

(8 1)
    I := 1
    V := 1 + 3 = 4
    MoveToFront(4): 9 10 11 7 8 1  ->  8 9 10 11 7 1
    T: (2 3 5)  ->  (1 2 3 5)

(7 0)
    I := 0
    V := 0 + 4 = 4
    MoveToFront(4): 8 9 10 11 7 1  ->  7 8 9 10 11 1
    T: (1 2 3 5)  ->  (0 1 2 3 5)

(1 4)
    I := 4
    V := 4 + 1 = 5
    MoveToFront(5): 7 8 9 10 11 1  ->  1 7 8 9 10 11
    T: (0 1 2 3 5)  ->  (0 1 2 3 4 5)

我想你可以找到使用少于n个MoveToFront / Back操作对这些数组进行排序的方法,但我认为你不能在O(n log n)时间内找到那些数组。但是,如果这些操作很慢,那么使用需要更多时间进行规划的算法可能是值得的,因此您可以减少这些操作。

答案 1 :(得分:0)

你能澄清一下这个问题吗?当你说列表时,你的意思是一个链表还是一个数组?如果它不是链表,我对有限的操作集感到有点困惑。如果它是链表,您可以修改以平均情况O(nlgn)时间运行的快速排序。

答案 2 :(得分:0)

基本上,您提到的数据结构是链接列表。对于链表,您可以使用quicksort或mergesort(O(nlogn))。

答案 3 :(得分:0)

这对我来说不像是排序问题。您需要找到需要执行的移动次数,但不需要对数组进行排序。我打赌可以比O(n log n)

更快地完成

我建议这样的解决方案: 只计算一个[i]> a [i - 1]。这将是你的结果。

论证: 如果你有[i]> a [i-1],意思是a [i]或[i-1]不在他们的位置。所以你可以:

1)将[i-1]移动到数组的开头

2)将[i]移动到数组的末尾。

更新。你需要定义你移动的[i]或[i-1],就像你的阵列示例一样:7 8 9 11 1 10你有两个比较,这显示了没有到位的内容:11> < 1&11> 10.因此,这绝对是动态编程的任务。但是,它仍然比O(n log n)

更快