特殊排序

时间:2012-06-26 06:56:11

标签: algorithm

有一个外部整数数组,您可以在O(1)时间内执行以下操作。

  1. get(int i) - 返回索引处的值' i'在外部阵列中。
  2. reverse(int i,int j) - 返回索引位置i和j(包括i和j)之间数组的反向。
  3. 反向示例:考虑数组{1,2,3,4,5}。 reverse(0,2)将返回{3,2,1,4,5},reverse(1,4)将返回{1,5,4,3,2}。

    编写代码以对外部数组进行排序。提及代码的时间和空间复杂性。

    显然我们可以使用快速排序或合并排序在nlogn中排序。但鉴于我们可以做得更好吗?

4 个答案:

答案 0 :(得分:3)

对数组进行排序是为了找到将其恢复到排序状态的排列或混洗。换句话说,您的算法确定必须应用哪些n!可能的排列,并应用它。由于您的算法通过询问是 - 否问题(小区i是否小于或大于小区j?)来探索数组,因此它遵循具有深度log(n!) ~ n*log(n)的隐式决策树。

这意味着会O(n*log(n))调用get()来确定如何对数组进行排序。

一个有趣的变体是,一旦你知道你需要什么样的排列,就可以确定对数组进行排序所需的最小调用次数reverse()。我们知道这个数字小于n-1,这可以通过使用选择排序来实现。最坏情况的数字是否可以小于n-2?我必须说我不知道​​......

答案 1 :(得分:2)

我尝试将问题简化为基于swaps()的经典排序算法。

在下文中,我们假设不失一般性j>=i
请注意,对于每个swap(i,j) = reverse(i,j) j <= i+2,如果有3个或更少的元素,则反转子数组仅交换边缘
现在,对于任何j>i+2 - 所有你需要的只是reverse()数组,通过交换边缘 - 然后反转“中间”以使其恢复原状,所以你得到:swap(i,j) = reverse(i,j) ; reverse(i+1,j-1)

使用刚构建的swap(),您可以使用任何使用互换的基于比较的算法,例如quicksort O(nlogn)。复杂性仍为O(nlogn),因为对于每个swap(),您最多需要2 reverse()个操作,即O(1)

编辑:注意:此解决方案适合原始问题(编辑之前),该问题要求解决方案,而不是更好地优化它然后快速排序/合并。

答案 2 :(得分:1)

假设您希望最大限度地减少外部操作getreverse的数量:

  • 通过调用get n次
  • 将所有整数读入内部数组
  • 进行内部排序(n登录内部操作)并计算排列
  • 通过调用reverse最多n次
  • 对外部数组进行排序

这具有O(n)时间和O(n)空间复杂度。

编辑以回应匿名downvotes: 在谈论时间复杂性时,你总是要说明要对哪些操作进行计算。我假设,只有外部操作才有成本。

答案 3 :(得分:0)

基于get(int i)和reverse(int i,int j),我们无法优化代码。它将具有相同的复杂性。