algorithm - 如何通过反转子序列对排列进行排序(取自 Skiena 第 3 版)

标签 algorithm sorting quicksort

在过去的 24 小时里,我一直在回答 Skiena(算法设计手册,第 3 版)提出的以下问题的第二部分,这让我抓狂!目前我正在努力想出新的想法,希望能提供一些提示/解决方案。

练习 4-27 假设给定一个从 nn 的整数排列 p,然后寻找 将它们排序为递增顺序 [1, . . . , n]。您唯一的操作 处置是reverse(p,i,j),它反转子序列(p_i, ..., p_j)的元素 在排列中。对于排列 [1, 4, 3, 2, 5] 一个反转(第二个 通过第四个元素)足以排序。

  • 证明可以使用 O(n) 次反转对任何排列进行排序。
  • 现在假设 reverse(p,i,j) 的成本等于它的长度,范围内的元素数量,|j − i| + 1. 设计一种算法,以 O(nlog^2n) 成本对 p 进行排序。

如果我们对它进行暴力破解,那么第一部分看起来相当简单:定位最大/最小值的位置并反转将其放置在正确位置的子序列。重复下一个最大/最小值,直到序列顺序正确。显然,这最多需要 n 个逆转。

但如果我将这种蛮力方法应用于问题的第二部分,在最坏的情况下,成本似乎可能是 O(n^2)。有人有什么建议吗?

最佳答案

有一个就地归并排序算法适合:

  1. 对数组的前半部分进行排序;
  2. 对数组的后半部分进行排序;
  3. 就地合并两半。

合并需要 O(N log N) 时间:

  1. 确定属于下半部分的前半部分元素个数;
  2. 将前半部分的最后元素与后半部分的前几个元素交换。你可以通过 3 个反转来做到这一点
  3. 递归合并前半部分和后半部分的两部分

由于合并需要 O(N log N) 时间,所以整个排序需要 O(N log2 N) 时间。

关于algorithm - 如何通过反转子序列对排列进行排序(取自 Skiena 第 3 版),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67770972/

相关文章:

java - 从十进制转换为十六进制

c++ - 在给定的字符串集中查找常见字符的数量?

ruby - 为什么这个 ruby 序列不适用于两位数?

c - 使用多个排序条件对数组进行排序(快速排序)

java - 排序:HashMap 和 Sets 的替代方案?

javascript - 对数组中的非后续元素进行排序

c - 二分查找 Int 数组大小问题

algorithm - 围绕对角线对矩阵元素进行排序

C++ std::sort 实现

php - 为什么 self 实现的快速排序比内部快速排序更快?