重新排列红蓝绿3色球 荷兰国旗问题
来源:互联网 发布:电脑总是弹出淘宝广告 编辑:程序博客网 时间:2024/05/02 00:26
Reorder Array of Red, Blue and Green balls(Dutch national flag problem)
一个有意思的问题:An array of some size contains Red, Blue and Green balls all mixed up randomly. like RGBBBRRGGG, where RGB is for Red, Green and Blue.
简单的说:有n个红蓝绿3种不同颜色的球,随机排成一列。现在需要使同种颜色的球排在一起并且按红蓝绿的顺序。(3中颜色简单的计为1 2 3)
这是经典的荷兰国旗问题(Dutch national flag problem,http://en.wikipedia.org/wiki/Dutch_national_flag_problem)。
1.当这个问题出现时,简单的方法是先扫描一遍序列,统计出各个颜色的个数,然后在数组中按各个颜色的个数填充各个颜色即可。
这个方法不错,但是需要2*n的时间。
2.这个问题类似于快速排序的数的交换。将比蓝色小的球放在左边,比蓝色大的球放在右边。 其中关键的是,出现了与蓝色相等的求的处理,例如:1 2 1 2 2 3 2 3的情况.
有一种处理方法,使用头尾两个指针,同时使用一个变量,记录第一次出现2颜色的位置(只需n步操作):
1.记录第一次出现2的位置。
2.头指针,从左向右扫描,a.出现比2小的的颜色,与第一次出现2的位置进行交换。如果没有出现过2,说明当前左边的颜色都比2小,无需处理。b.当出现比2大的颜色,记录位置,跳出。
3.尾指针,从右向左扫描,a.出现比2小的颜色,与第一次出现2的位置进行交换后,将交换后的颜色与上一步出现的比2大的颜色交换,跳出。b.出现和2相等的颜色,直接与上一步出现的比2大的颜色交换,跳出。
4.重复1 2 3步,直到头尾指针相遇。
#include <iostream>#include<stdlib.h>#include<stdio.h>#include<string.h>using namespace std;void swap(int *a, int *b){int tmp=*a;*a=*b;*b=tmp;}void partition_three_color(int *a,int low,int high){int i,j,tmp=-1;for(i=low;i<=high;i++){if(a[i]>2)//big color ,break, start from end to find a little colorbreak;else if(a[i]==2&&tmp==-1){//store the first 2tmp=i;}else{//now is small than 2, swap the first 2if(-1!=tmp){swap(a[i],a[tmp]);tmp++;}}}for(j=high;j>i;j--){if(a[j]<2){//find a little to swap big colorswap(a[tmp],a[j]);swap(a[j],a[i]);break;}else if(2==a[j]){//direct swapswap(a[i],a[j]);break;}}if(i+1<j-1)partition_three_color(a,i+1,j-1);}int main(){int n,i;while(scanf("%d",&n)!=EOF){//input total numbersint *arr=new int[n];for(i=0;i<n;i++){scanf("%d",&arr[i]);//only 1,2,3 three colorsif(arr[i]>3||arr[i]<1){printf("Invalid\n");return 0;}}partition_three_color(arr,0,n-1);for(i=0;i<n;i++)printf("%d ",arr[i]);printf("\n");}return 0;}
给几组测试数据:
82 1 3 3 2 2 1 31121 331 2 332 1 3
下面是WIKI的解释和方法(详细见:http://en.wikipedia.org/wiki/Dutch_national_flag_problem):
这个问题可以被看出是一个数组排序问题。假设每一个元素都可以被归为1、2、3(小,中,大) 三类当中的一个。 算法就是将属于每一类的元素归到相应的类,1类在2类前面,3类在2类后面。算法记录3个位置:最大类的下限,最小类的上限,中间类的上限。
如果当前元素属于大类,将该元素与大类下限后的一个元素交换。q--
如果当前元素属于小类,将该元素与小类上限上的一个元素交换。p++
如果属于中类,不处理.
下面是算法
#include <iostream>#include<stdlib.h>#include<stdio.h>#include<string.h>using namespace std;void swap(int *a, int *b){int tmp=*a;*a=*b;*b=tmp;}void three_way_partition(int *a,int size){int p=-1;int q=size;for(int i=0;i<q;){if(a[i]==1){swap(a[i],a[++p]);i++;}else if(a[i]==3){swap(a[i],a[--q]);}elsei++;}}int main(){int n,i;while(scanf("%d",&n)!=EOF){//input total numbersint *arr=new int[n];for(i=0;i<n;i++){scanf("%d",&arr[i]);//only 1,2,3 three colorsif(arr[i]>3||arr[i]<1){printf("Invalid\n");return 0;}}three_way_partition(arr,n);for(i=0;i<n;i++)printf("%d ",arr[i]);printf("\n");}return 0;}
- 重新排列红蓝绿3色球 荷兰国旗问题
- 荷兰3色国旗问题
- 荷兰国旗问题
- 荷兰国旗问题
- 荷兰国旗问题
- 荷兰国旗问题
- 荷兰国旗问题
- 荷兰国旗问题
- 荷兰国旗问题
- 荷兰国旗问题
- 荷兰国旗问题
- 荷兰国旗问题
- 荷兰国旗问题
- 荷兰国旗问题
- 荷兰国旗问题
- NYOJ_268荷兰国旗问题
- 荷兰国旗问题
- 荷兰国旗问题
- UVALive 6163 - Myth Busters
- C++精确获取时间(QueryPerformanceCounter)
- 实用的正则表达式
- C++ STL入门教程(6)——set(集合)的使用(附完整程序代码)
- 获取汉字拼音首字母
- 重新排列红蓝绿3色球 荷兰国旗问题
- There is no result map named seatCache.SeatInfo in this SqlMap
- hdu 1059二进制优化背包问题
- Qt:sizePolicy属性
- 职业发展 先“立功”还是先“安内”?
- nyoj-108-士兵杀敌(一)
- Android的所有权限说明
- 一个程序员应具备的素质
- 最新版 Android SDK 无法获取SDK包 的解决方案