有一个数组A = [a1,a2,...,an],其中数组中的每个元素都是0,1或2.
需要对数组进行排序,但具体说明是使用基于比较的算法。我知道可以使用线性时间算法,但不允许使用计数排序或其他数组。
任何人都可以帮助我从哪里开始。我假设我们知道1是中位数,但是你会使用什么技术对它进行排序?
答案 0 :(得分:4)
将1作为枢轴元素。与每个元素比较。如果是0
,请在1
之前移动它,如果是2
,则在1
之后移动它。
#include <iostream>
#include <vector>
#include <iterator>
using namespace std;
void Sort(vector<int>& A) {
int n = A.size(), i = 0, j = 0, k = n - 1;
while (j < k) {
if (A[j] == 0) swap(A[i++], A[j++]);
else if (A[j] == 2) swap(A[k--], A[j]);
else ++j;
}
}
int main() {
vector<int> A {2, 1, 2, 1, 0};
Sort(A);
copy(A.begin(), A.end(), ostream_iterator<int>(cout, " "));
return 0;
}
答案 1 :(得分:2)
通过仅比较元素,可以对只有3个值的数组进行排序(即使不知道元素的类型或三个值,当给定比较函数时),例如像这样:
比较前两个元素;如果一个大于另一个,则较小的一个是0或1,较大的一个是1或2.将较小的一个放在前面,并将较大的一个与最后一个元素交换。然后比较第二个(交换的)和第三个元素,将较小的一个放在第二个位置,并将较大的一个与最后一个元素交换,依此类推。如果两个元素相等,则将它们与第三个元素进行比较,依此类推,直到找到差异为止,并在必要时将几个元素移动到末尾。
这是一个数组,其中第一个区域全部为0或1,第二个区域全部为1或2.然后可以以类似的方式对这些区域中的每个区域进行排序,从而生成完全排序的数组迭代数组两次。
示例:
state: 2,1,2,1,0
compare: ^ ^
swap: 1,2,2,1,0
move: ^ ^
state: 1,0,2,1,2
compare: ^ ^
swap: 1,0,2,1,2
move: ^ ^
state: 1,0,1,2,2
因为有奇数个元素,我们必须通过将它与前一个元素进行比较来检查中间元素是属于第一个还是第二个区域(如果它们与下一个元素相同)。在示例中,中间元素是1,因此它并没有真正发挥作用。
现在我们有两个区域:
zone1: 1,0
zone2: 1,2,2
然后可以分别对这些中的每一个进行分类:
state: 1,0
compare: ^ ^
swap: 0,1
state: 1,2,2
compare: ^ ^
swap: 1,2,2
move: ^ ^
state: 1,2,2
在这个阶段,我们不必检查奇数区域中的中间元素。
答案 2 :(得分:0)
这是一个javascript解决方案。算法运行两次,其中pivot = 1,pivot = 0,基于分区。您可以看到算法执行COMPARISION而不是知道0,1或2。
var array = [1,0,2,0,0,1,2,0,2,1,1,1,2,2,0,0,0,1];
console.log("Original Array " + array);
var size = array.length;
function partition(array, s, e, pivot) {
var i = s - 1;
var j = s;
while (j < e) {
if (array[j] <= pivot) {
var swap = array[i + 1];
array[i + 1] = array[j];
array[j] = swap;
i++;
}
j++;
}
return i;
}
var parti = partition(array, 0, size, 1)
console.log("After one pass " + array);
console.log("Partition " + parti);
partition(array, 0, parti + 1, 0);
console.log("Final Array " + array);