Algorithm 特殊分类

Algorithm 特殊分类,algorithm,Algorithm,有一个外部整数数组,您可以在O(1)时间内对其执行以下操作 get(int i)-返回外部数组中索引“i”处的值 反向(inti,intj)-返回索引位置i和j(包括i和j)之间数组的反向 反向示例:考虑数组{1,2,3,4,5 }。反向(0,2)将返回{3,2,1,4,5},反向(1,4)将返回{1,5,4,3,2} 编写代码对外部数组进行排序。提及代码的时间和空间复杂性 显然,我们可以使用快速排序或合并排序在nlogn中进行排序。但是考虑到这种情况,我们能做得更好吗?我会尝试将问题简化为一种

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

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

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


    显然,我们可以使用快速排序或合并排序在nlogn中进行排序。但是考虑到这种情况,我们能做得更好吗?

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

    在下文中,我们假设在不丧失一般性的情况下,
    j>=i

    请注意,
    swap(i,j)=reverse(i,j)
    对于每个
    ji+2
    -您所需要的只是
    reverse()
    数组,通过交换边-然后反转“中间”以使其返回原始,因此您得到:
    swap(i,j)=reverse(i,j);反向(i+1,j-1)

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


    编辑:注意:此解决方案适用于原始问题(编辑前),要求提供解决方案,而不是比快速排序/合并排序更好地对其进行优化

    假设您希望最小化外部操作的数量
    get
    reverse

    • 通过调用
      get
      n次,将所有整数读入内部数组
    • 进行内部排序(n在内部操作中登录)并计算排列
    • 通过调用
      reverse
      最多n次对外部数组进行排序
    这具有O(n)时间和O(n)空间复杂性

    编辑以响应匿名否决票:
    当谈到时间复杂度时,您总是必须说明哪些操作需要计数。在这里,我假设只有外部操作有成本。

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

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

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


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

    计算复杂性时只计算get和reverse,内部操作是免费的?需要使用get()和reverse()对数组进行排序吗?我想我们需要基于这些进行优化。。。我们可以使用快速排序或合并排序在nlogn中进行排序,但鉴于这种情况,我们能做得更好吗?究竟为什么有人可以否决这么好的问题…这会阻止人们发布任何有趣的问题…@user973931这是一个坏问题,因为不清楚,例如,是否要考虑内部操作的成本。这已经导致了混乱,并导致了许多反对票。这并不能回答问题(
    ,但考虑到目前的情况,我们能做得更好吗?
    )。@WolframH:引用的那句话不在原始问题中。这个答案适用于问题的原始版本,它只问“如何才能做到?”是的。(我想,评论中也提到了这个解决方案。哦,是你的评论…(我没有投反对票,这只是一个信息性的评论。)@WolframH:是的,我认为它更适合作为一个答案。不管怎么说,答案确实为原始问题提供了一个解决方案,通过使用一个众所周知的领域,这通常是首选。请在您的答案中提及原始问题,我将向上投票。事实上,“新来者”有可能会感到困惑。这似乎是在违反规则。为什么您认为计数
    get
    reverse
    就足以计算时间复杂度?你怎么知道你有内存?假设是不够的,我的假设正好相反。有人甚至可以假设存在一个并没有提到的O(1)类外部数组。@JurajBlaho-哪个规则?规则没有完全说明,所以我填补了空白。我的假设可能正确,也可能不正确。但基于这个假设,我认为我的答案是正确的。是的,我同意,规则并不明确。但是如果你可以任意地填补这个空白,你可以在O(1)中做到。规则没有声明没有内部内存,也没有声明没有O(1)排序操作。所以我认为答案是不正确的,这就是为什么我投了反对票。@JurajBlaho-不,你永远不能在O(1)中这样做。考虑到get和reverse的成本为O(1)这一事实,您将如何对O(1)中的外部数组进行排序?@JurajBlaho-我没有进行O(1)外部排序。考虑到外部阵列的访问是昂贵的,例如因为它在远程计算机上。然后,读入所有数据,进行内部排序(O(nlogn)内部操作,但这些操作很便宜),然后向远程计算机发出O(n)反向命令是有意义的