如何在时间和空间复杂度的限制下交替对偶数和奇数进行排序?(C/C++)

How to sort even and odd numbers alternatively with the limit of time and space complexity?(C/C++)

本文关键字:排序 C++ 空间复杂度 时间      更新时间:2023-10-16

给定一个像这样的integer array

int numbers[8]={1, 3, 5, 7, 8, 6, 4, 2};

前面数组中的半边是奇数,其余的(等量数)是偶数。奇数按升序排列,偶数按降序排列。排序后,无法更改数字的顺序。

如何以小于O(n^2)的时间复杂度和空间复杂O(1)对它们进行交替排序?

对于此示例,结果将为:{1,8,3,6,5,4,7,2} ;

我不能使用外部阵列存储,但临时变量是可以接受的。

我尝试使用两个指针(oddPtr, evenPtr)分别指向奇数和偶数,并移动evenPtr将偶数值插入奇数的中间。(如插入排序)
但这需要O(n^2).

更新

根据Dukeling的评论,我意识到我提出的解决方案实际上不是线性的,而是线性的,甚至更糟 - 您无法控制它是否需要额外的内存。在我的第二个想法中,我意识到您对实现更具体但可能更简单的解决方案的阵列了解很多。

我将假设数组中的所有值都是正数。我需要这个,以便我可以使用负值作为"已处理"标志。我的想法如下 - 从左到右迭代数组。对于每个元素,如果它已经被处理(即它的值是负数),只需继续下一个元素。否则,您将有一个常量公式,其中 是此元素应位于的位置:

  • 如果值为奇数且其索引i则应移至i*2
  • 如果值是偶数并且其索引i则它应该移动到(i - n/2)*2 + 1

将此值存储到临时值中,并使数组当前索引处的值为 0。现在,直到我们"手头"的值不为零的位置,将其与根据上述公式应放置在的位置的值交换。此外,当您将值放在手边时,请将其否定为"将其标记为已处理"。现在我们手头有一个新值,我们再次根据上面的公式计算它应该去哪里。我们继续移动值,直到我们"手头"的值应该达到 0 的位置。稍加思考,您就可以证明您手头永远不会有负("已处理")值,最终您将在数组的空白处结束。

处理完所有值后,遍历数组一次以否定所有值,您将拥有所需的数组。我描述的算法的复杂性是线性的 - 每个值不会超过一次"在手边",并且您将迭代它不超过一次。