如何在没有新数组的情况下对数组进行排序?

时间:2016-10-04 15:19:23

标签: java sorting

我正在做我的作业,并且有一个问题要求我们对结构数组进行排序

结构citizenint idboolean gender组成,其中id是在1到100之间随机生成的, gender取决于id是奇数还是偶数,奇数= true(男性)甚至= false(女性)

例如a = {33, true}

这个问题要求我按性别对citizen[]数组进行排序,看起来很简单,但它有以下要求:

  

以线性时间O(N)

运行      

没有新阵列

     

只能使用恒定的额外空间

我正在考虑使用计数排序,但是如果没有新数组,似乎有点难以实现,是否有任何建议?

3 个答案:

答案 0 :(得分:8)

由于这是一个家庭作业问题,我不打算提供代码。以下内容足以让您入门。

按性别“排序”这里实际上意味着分成两组。通用排序不能比O(n * log(n))更好,但是可以在具有恒定空间的O(n)中进行分区。

考虑同时从两端迭代(while循环,两个索引指针初始化为first和last元素),寻找“错误”部分中的元素。当你在每一端找到一个这样的元素时,交换它们。请注意,指针只在跳过已经在右边部分的元素时才会相互独立移动,当然也可以在交换后立即移动,这是“已经在右边部分中的元素”的子例。

当索引指针在中间某处相遇时退出。

这不是一般目的。如果密钥数量未知,则无法执行此操作。

答案 1 :(得分:3)

由于您只有两个要排序的值,您可以使用一种交换计数排序(我无法找到任何相关的论文)。 在那种情况下有优化的空间,但这将是你的工作。

根据您的问题,这是一个特殊排序的伪代码:

integer maleIndex = 0   // Current position of males in the array

for i=0 until array.size do
   if array.at(i) is a male then

      // after a while, all female will end up at the end
      // while all male will end up at the beginning
      swap(array.at(maleIndex), array.at(i))
      maleIndex = maleIndex + 1
   end
end

答案 2 :(得分:2)

一种方法类似于QuickSort中的分区阶段,或类似于中值/等级查找算法QuickSelect。

我将描述算法的大纲,但不提供任何代码。希望翻译很容易。

您基本上想要重新组织数组,以便一个性别位于开头,另一个位于数组的末尾。您将阵列分为三个部分:

  • 从0到i-1,您有第一个性别(男性或女性,由您决定)
  • 从i到j-1,你有男/女。这是未知领域。
  • 从j到n-1,你有第二个性别。

在算法开始时,i设置为0,因此第一个区域为空,j设置为n-1,因此第二个区域为空。基本上整个阵列都处于未知状态。

然后,以特定方式迭代数组。在每一步,你看看公民[i] .gender。如果它是第一个性别,你可以不管它并增加i。如果是第二性别,则将A [i]与A [j]交换并递减j。当我等于j时你停止。

为什么这是正确的?好吧,在每一步我们都可以看到保持三个区域的约束,假设它保持开始(它确实),并且第一个或第二个区域增加。最后,第二个区域没有元素,因此我们只在开始时留下第一个性别,在结束时留下第二个性别。

为什么它是线性的?好吧,在每一步中,我们都会对数组中的一个元素做出一个恒定时间的决定。有这样的元素,所以时间是线性的。或者,迭代测试可以表示为while (j - i > 0),表达式j - in-1开始,每次迭代都会减少1