算法描述:
三色旗的问题最早由E.W.Dijkstra所提出,他所使用的用语为Dutch Nation Flag(Dijkstra为荷兰人),而多数的作者则使用Three-Color Flag来称之。
解法:
只是要让移动次数最少的话,就要有些技巧:
如果图中w所在的位置为白色,则w+1,表示未处理的部份移至至白色群组。
如果w部份为蓝色,则b与w的元素对调,而b与w必须各+1,表示两个群组都多了一个元素。
如果w所在的位置是红色,则将w与r交换,但r要减1,表示未处理的部份减1。
注意的细节:
第一,当w指向的是红色而和r交换时,如果此时r指向的是红色,显然没有必要把两个红色的旗子交换。所以这时应该把r前移,直到r指向的不是红色的时候才和w指向的旗子交换。当然移动时必须确保w<r。
第二,同样地,当w指向的是蓝色而要和b的指向交换时,如果b指向的不是蓝色,则交换。否则如果b指向的是蓝色,则也没有必要把两个蓝色的旗子交换。所以这时应该把b和w都往后移一位。
注意b、w、r并不是三色旗的个数,它们只是一个移动的指针;什幺时候移动结束呢?一开始时未处理的r指针处于最后一个旗子位子,当r的索引数减至少于w的索引数时,表示接下来的旗子就都是红色了,此时就可以结束移动。
运行结果:
三色旗的问题最早由E.W.Dijkstra所提出,他所使用的用语为Dutch Nation Flag(Dijkstra为荷兰人),而多数的作者则使用Three-Color Flag来称之。
假设有一条绳子,上面有红、白、蓝三种颜色的旗子,起初绳子上的旗子颜色并没有顺序,您希望将之分类,并排列为蓝、白、红的顺序,要如何移动次数才会最少,注意您只能在绳子上进行这个动作,而且一次只能调换两个旗子。示意图:
解法:
在一条绳子上移动,在程式中也就意味只能使用一个阵列,而不使用其它的阵列来作辅助,问题的解法很简单,您可以自己想像一下在移动旗子,从绳子开头进行,遇到蓝色往前移,遇到白色留在中间,遇到红色往后移。
只是要让移动次数最少的话,就要有些技巧:
如果图中w所在的位置为白色,则w+1,表示未处理的部份移至至白色群组。
如果w部份为蓝色,则b与w的元素对调,而b与w必须各+1,表示两个群组都多了一个元素。
如果w所在的位置是红色,则将w与r交换,但r要减1,表示未处理的部份减1。
注意的细节:
第一,当w指向的是红色而和r交换时,如果此时r指向的是红色,显然没有必要把两个红色的旗子交换。所以这时应该把r前移,直到r指向的不是红色的时候才和w指向的旗子交换。当然移动时必须确保w<r。
第二,同样地,当w指向的是蓝色而要和b的指向交换时,如果b指向的不是蓝色,则交换。否则如果b指向的是蓝色,则也没有必要把两个蓝色的旗子交换。所以这时应该把b和w都往后移一位。
注意b、w、r并不是三色旗的个数,它们只是一个移动的指针;什幺时候移动结束呢?一开始时未处理的r指针处于最后一个旗子位子,当r的索引数减至少于w的索引数时,表示接下来的旗子就都是红色了,此时就可以结束移动。
Java 代码实现:
public static void main(String[] args) {
char[] threeFlag = new char[]{'R','B','R','W','R','R','W','B','B','W'};
int bPointer = 0;
int wPointer = 0;
int rPointer = threeFlag.length - 1;
printProcess(threeFlag, bPointer, wPointer, rPointer);
while (wPointer < rPointer) {
if (threeFlag[wPointer] == 'B') {
char temp = threeFlag[bPointer];
threeFlag[bPointer] = threeFlag[wPointer];
threeFlag[wPointer] = temp;
bPointer++;
wPointer++;
} else if (threeFlag[wPointer] == 'W') {
wPointer++;
} else if (threeFlag[wPointer] == 'R') {
char temp = threeFlag[rPointer];
threeFlag[rPointer] = threeFlag[wPointer];
threeFlag[wPointer] = temp;
rPointer--;
}
printProcess(threeFlag, bPointer, wPointer, rPointer);
}
}
public static void printProcess(char[] threeFlag, int bPointer, int wPointer, int rPointer) {
char arrow = '↓';
String space1 = " ";
String space2 = " ";
String space3 = " ";
String s1 = "";
String s2 = "";
for (int i=0; i<threeFlag.length; i++) {
if ((bPointer == wPointer) && (bPointer==i)) {
s1 = s1 + "bw" + space1;
s2 = s2 + arrow + arrow + space1;
} else if ((wPointer == rPointer) && (wPointer==i)) {
s1 = s1 + "wr" + space1;
s2 = s2 + arrow + arrow + space1;
} else {
if (bPointer == i) {
s1 = s1 + "b" + space2;
s2 = s2 + arrow + space2;
} else if (wPointer == i) {
s1 = s1 + "w" + space2;
s2 = s2 + arrow + space2;
} else if (rPointer == i) {
s1 = s1 + "r" + space2;
s2 = s2 + arrow + space2;
} else {
s1 = s1 + space3;
s2 = s2 + space3;
}
}
}
String s3 = "";
String s4 = "";
String split = "---";
for (int i=0;i<threeFlag.length;i++) {
s3 = s3 + threeFlag[i] + space2;
s4 = s4 + split;
}
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
System.out.println(s4);
}
运行结果: