有一个外部整数数组,您可以在O(1)时间内执行以下操作。
反向示例:考虑数组{1,2,3,4,5}。 reverse(0,2)将返回{3,2,1,4,5},reverse(1,4)将返回{1,5,4,3,2}。
编写代码以对外部数组进行排序。提及代码的时间和空间复杂性。
显然我们可以使用快速排序或合并排序在nlogn中排序。但鉴于我们可以做得更好吗?
答案 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)
假设您希望最大限度地减少外部操作get
和reverse
的数量:
get
n次reverse
最多n次这具有O(n)时间和O(n)空间复杂度。
编辑以回应匿名downvotes: 在谈论时间复杂性时,你总是要说明要对哪些操作进行计算。我假设,只有外部操作才有成本。
答案 3 :(得分:0)
基于get(int i)和reverse(int i,int j),我们无法优化代码。它将具有相同的复杂性。