荷兰国旗有三横条块,自上到下的三条块颜色依次为红、白、蓝。
现有若干由红、白、蓝三种颜色的条块序列,要将它们重新排列使所有相同颜色的条块在一起。
本问题要求将所有红色的条块放最左边、所有白色的条块放中间、所有蓝色的条块放最右边。 且时间复杂度为O(n);
#include<stdio.h>
typedef enum{RED,WHITE,BLUE} color;//实际为 0,1,2
void FlagArrange(color a[],int len){
int i=0,j=0,k=len; color temp;
while(j<=k){
switch(a[j]){ //判断条块颜色
case RED:temp=a[j];a[j]=a[i];a[i]=temp;i++,j++;break; //红色,则i交换
case WHITE:j++;break; //
case BLUE:temp=a[j];a[j]=a[k];a[k]=temp;k--; //蓝色,则和k交换
//这里没有进行j++以防止交换后a[j]仍为蓝色
}
}
}
int main(){
color a[]={BLUE,WHITE,WHITE,RED,RED,BLUE,BLUE};
int len=sizeof(a)/sizeof(color);
FlagArrange(a,len-1);
for(int i=0;i<len;i++){
printf("%d ",a[i]);
}
}
#include<stdio.h>
typedef enum{RED,WHITE,BLUE} color;//实际为 0,1,2
void FlagArrange(color a[],int len){
int i=0,j=0,k=len; color temp;
//其中i指向白色第一个(最后一个红色+1)
//j指向蓝色第一个(最后一个白色+1)
//k指向待判断元素
while(j<k){
switch(a[k]){ //判断条块颜色
case RED:temp=a[k];a[k]=a[i];a[i]=temp;i++,j++;break; //红色,则i交换
case WHITE:temp=a[k];a[k]=a[j];a[j]=temp;j++;break; //白色,则和j交换
case BLUE:k--;break;
}
}
}
int main(){
color a[]={BLUE,WHITE,WHITE,RED,RED,BLUE,BLUE};
char * colors[]={"RED","WHITE","BLUE"};//c++环境下修改为 const char * colors[]={"RED","WHITE","BLUE"};
int len=sizeof(a)/sizeof(color);
FlagArrange(a,len-1);
for(int i=0;i<len;i++){
printf("%s ",colors[a[i]]);
}
}
国旗问题变种问题:将数组元素值按负、零、正的顺序进行排列。
#include<stdio.h>
void FlagSort(int a[],int len){
//将元素值按负、零、正的顺序进行排列
int i=0,j=0,k=len;
int temp;int sign;
while(j<=k){
//if(a[j]>0)sign=1;else if(a[j]<0) sign=-1;else sign=0;//判断数组元素正负性
sign=(a[j]==0)?0:(a[j]>0)?1:-1;//用三元表达式实现上面一行代码;
switch(sign){
case -1:temp=a[j];a[j]=a[i];a[i]=temp;i++,j++;break;
case 0:j++;break;
case 1:temp=a[j];a[j]=a[k];a[k]=temp;k--;
}
}
}
int main(){
int a[]={-1,-2,-3,4,5,6,-7,-8,9,0};
int len=sizeof(a)/sizeof(int);
FlagSort(a,len-1);
for(int i=0;i<len;i++){
printf("%d ",a[i]);
}
}