问题描述:现有红,白,蓝三个不同颜色的小球,乱序排列在一起,请重新排序这些小球,使得红白蓝三色的同颜色的球在一起这个问题之所以叫荷兰国旗,是因为我们可以将红白蓝三色小球想想成条状物,有序排列后正好组成荷兰国旗。问题转化为:给定数组A[0…N-1],元素只能取0,1,2三个值,设计算法,使得数组排列成“000…00…11…11…22…22"形式。
1.实现思路:使用三个指针,分别指向首尾和当前位置cur指向1的末尾,begin指向0的末尾,end指向2的开始,依次遍历即可。
①实现方法如下:
void holland(int* a,int size) {
int begin = 0;
int cur = 0;
int end = size - 1;
while (cur<=end)
{
if (a[cur]==2)
{
swap(a[cur], a[end]);
end--;
}
else if(a[cur]==1)
{
cur++;
}
else//a[cur]=0
{
if (begin==cur)
{
begin++;
cur++;
}
else
{
swap(a[begin], a[cur]);
begin++;
}
}
}
}
②上述代码优化
优化1(核心:当a[begin]和a[cur]交换后,a[cur])必为1,所以cur直接++:
void holland1(int* a, int size) {
int begin = 0;
int cur = 0;
int end = size - 1;
while (cur <= end)
{
if (a[cur] == 2)
{
swap(a[cur], a[end]);
end--;
}
else if (a[cur] == 1)
{
cur++;
}
else//a[cur]=0
{
//if (begin == cur)
//{
// begin++;
// cur++;
//}
//else
//{
// swap(a[begin], a[cur]);
// //当begin! = cur时,交换过后,a[cur]=1(归纳法得出),所以可以直接cur++
// begin++;
// cur++;
//}
//上述注释代码的简化
if (begin!=cur)
{
swap(a[begin], a[cur]);
}
begin++;
cur++;
}
}
}
优化2:(改变cur的初始指向,从后向前)
void holland2(int a[], int size) {
int begin = 0;
int end = size - 1;
int cur = end;
while (cur>=begin)
{
if (a[cur]==2) {
swap(a[cur], a[end]);
end--;
cur--;
}
else if(a[cur]==1)
{
cur--;
}
else //a[cur]=0
{
swap(a[cur], a[begin]);
begin++;
}
}
}
若有任何问题,欢迎读者随时批评指正,万分感谢!!