荷兰的国旗由红色、白色和蓝色3种颜色组成。现在假设有很多这3种颜色的线被存放在一个数组里,要求每次操作仅能进行一次交换,在原数组的基础上操作。待对数组进行一遍扫描后,3种颜色自然分开,颜色顺序为红、白、蓝。另外,要求在O(n)的复杂度下,是移动次数最少。
//荷兰国旗问题
#include <iostream>
#include <cstdlib>
using namespace std;
const int N = 100;
int flag[N];//存放颜色数组
int pre[N];//记录红色位置数组
int split1; //红色和白色的分割点
int split2;//白色和蓝色的分割点
int red_blue; //红色在蓝色区域的部分
int red_white;//红色在白色区域的部分
int counts = 0;//记录交换次数
void print();//输出
void swap(int & x,int & y);//交换
void fun();//实现
void init();//初始化
int main()
{
init();
cout<<"原始: "<<endl;
print();
fun();
cout<<"移动"<<counts<<"次"<<endl;
print();
return 0;
}
void print()
{
for (int i = 0; i < N; i++)
{
cout<<flag[i];
}
cout<<endl;
}
void swap(int & x,int & y)
{
int temp = x;
x = y;
y = temp;
counts++;
}
void fun()
{
for (int i = 0; i < split1; i++)//交换红色与非红色部分
{
if (flag[i] != 0)
{
if (red_blue >= split2)
{
swap(flag[i],flag[red_blue]);
red_blue = pre[red_blue];
}
else
{
swap(flag[i],flag[red_white]);
red_white = pre[red_white];
}
}
}
int b = N - 1;
for (int j = split1; j < split2; j++)//排序白色和蓝色
{
if (flag[j] != 1)
{
while(flag[b] == 2)
{
b--;
}
swap(flag[j],flag[b]);
b--;
}
}
}
void init()
{
int red_num = 0;//红色个数
int white_num = 0;//白色个数
int preI = -1;
for (int i = 0; i < N; i++)
{
flag[i] = rand() % 3;
if (flag[i] == 0)
{
red_num++;
pre[i] = preI;
preI = i;
}
else if (flag[i] == 1)
{
white_num++;
}
}
split1 = red_num;
split2 = red_num + white_num;
red_blue = preI;
int j = split2 - 1;
while(flag[j] != 0)
{
j--;
}
red_white = j;
}