【问题标题】:Minimal Number of Extract + Inserts required to sort a list对列表进行排序所需的最少提取次数 + 插入次数
【发布时间】:2026-02-01 08:20:02
【问题描述】:

上下文

这个问题是由于试图尽量减少昂贵的函数调用次数

问题定义

请注意 extract_and_insert != 交换。特别是,我们从位置“from”取出元素,将其插入位置“to”,然后SHIFT所有中间元素。

int n;
int A[n]; // all elements are integer and distinct



function extract_and_insert(from, to) {

  int old_value = A[from]

  if (from < to) {
    for(int i = from; i < to; ++i)
      A[i] = A[i+1];
    A[to] = old_value;
  } else {
    for(int i = from; i > to; --i)
      A[i] = A[i-1];
     A[to] = old_value;
  }
}

问题

我们知道有 O(n log n) 算法可以对数字列表进行排序。

现在:是否有一个 O(n log n) 函数,它返回 对列表进行排序所需的 extract_and_insert 的最小调用次数

【问题讨论】:

  • @AlmaDo:这不是问题所在。问题是:“是否有一个 O(n log n) 算法可以返回对列表进行排序所需的最少调用次数extract_and_insert?”
  • @Dukeling:确实,这两个问题是一样的。没有找到原始问题是我的错。但是,鉴于已经发布了答案,我们不要删除此问题。

标签: algorithm sorting


【解决方案1】:

答案是是的

这个问题本质上相当于在一个数组中找到longest increasing subsequence (LIS),你可以使用算法来解决这个问题。

为什么这个问题相当于最长递增子序列?

因为每个extract_and_insert 操作将在最有效的情况下更正数组中恰好一个元素的相对位置。换句话说,当我们考虑数组的最长递增子序列的长度时,每个操作都会将该长度增加 1。因此,所需调用的最小次数是:

length_of_array - length_of_LIS

因此通过查找 LIS 的长度,我们将能够找到所需的最小操作数。

请阅读链接的 Wikipedia 页面以了解如何实现该算法。

【讨论】:

    最近更新 更多