1. 程式人生 > >三色棋問題(荷蘭國旗問題)

三色棋問題(荷蘭國旗問題)

假設有一條繩子,上面有紅、白、藍三種顏色的旗子,起初繩子上的旗子顏色並沒有順序,您希望將之分類,並排列為藍、白、紅的順序,要如何移動次數才會最少,注意您只能在繩子上進行這個動作,而且一次只能調換兩個旗子。
在一條繩子上移動,在程式中也就意味只能使用一個陣列,而不使用其它的陣列來作輔助,問題的解法很簡單,您可以自己想像一下在移動旗子,從繩子開頭進行,遇到藍色往前移,遇到白色留在中間,遇到紅色往後移,如下所示: 

只是要讓移動次數最少的話,就要有些技巧:

  1. 如果圖中W所在的位置為白色,則W+1,表示未處理的部份移至至白色群組。
  2. 如果W部份為藍色,則B與W的元素對調,而B與W必須各+1,表示兩個群組都多了一個元素。
  3. 如果W所在的位置是紅色,則將W與R交換,但R要減1,表示未處理的部份減1。


注意B、W、R並不是三色旗的個數,它們只是一個移動的指標;什麼時候移動結束呢?一開始時未處理的R指標會是等於旗子的總數,當R的索引數減至少於W的索引數時,表示接下來的旗子就都是紅色了,此時就可以結束移動,如下所示:  

public String move(char[] flags) 
    
{        
        
int wFlag =0;        
        
int bFlag =0;        
        
int rFlag = flags.length -1;           
        
while(wFlag <= rFlag) 
        
{            
            
if(flags[wFlag] =='W'
            
{                
                wFlag
++;            
            }
            
            
elseif(flags[wFlag] =='B'
            
{                
                swap(flags, bFlag, wFlag);                
                bFlag
++;                
                wFlag
++;            
            }
            
            
else 
            
{                
                
while(wFlag < rFlag && flags[rFlag] =='R')                    
                    rFlag
--;                
                swap(flags, rFlag, wFlag);                
                rFlag
--;                            
            }
        
        }
                        
        
returnnew String(flags);    
    }
        
    

    
privatevoid swap(char[] flags, int x, int y) 
    
{        
        
char temp;        
        temp 
= flags[x];        
        flags[x] 
= flags[y];        
        flags[y] 
= temp;    
    }