標籤:荷蘭國旗問題
時間:2014.08.07
地點:基地
----------------------------------------------------------------------------------
一、題目描述
現有紅白藍三個不同顏色的小球,亂序排列在一起,重新排列這些小球,使得紅白藍三色的同顏色的球在一起。這個問題之即荷蘭國旗問題,將紅白藍三色小球想象成條狀物,有序排列後正好組成荷蘭國旗。如所示:
----------------------------------------------------------------------------------
二、思路2.1方法一:排序
若是把顏色與數值對應起來,其實是個簡單的排序問題,只不過元素取值只含3個,且有重複,不妨設為0 1 2 ,
於是採用各種排序都可解決。時間複雜度對於各種排序方法對應的時間複雜度。
2.2方法二:劃分
將元素劃分成三個部分,思路:
2.2.1 設定三個指標begin current end,begin current初始化指向數組首元素,end初始化指向數組尾元素
2.2.2 檢查current指向的值,為 0 :則與begin交換值,然後current begin均後移一個位置
為1 :則begin不動,current後移一個位置
為2:則與end交換值,然後current後移一個位置,end前移一個位置
2.2.3重複上述過程,當current>end時停止,注意這裡的條件不可以取等於(比如在序列中如果存在連續的 2 0,恰好current指向2,end指向0,則交換後為0 2,而這之前可能還有1,此時還不能終止重複過程。時間複雜符為O(n)
代碼如下:
//荷蘭國旗問題2014.08.07#include<iostream>#include<vector>#include<algorithm>void Partition(std::vector<int>& vec){auto begin = vec.begin();auto end = vec.end() - 1;auto cursor = begin;while (cursor <= end){if (0 == *cursor){std::swap(*cursor, *begin);++begin;++cursor;}else if (1 == *cursor)++cursor;else{std::swap(*cursor, *end);--end;}}}int main(){std::vector<int> vec{0, 1, 1,1,2,0,2,1,0, 2, 0, 2 };Partition(vec);for (auto element : vec)std::cout << element << ' ';std::cout << std::endl;}
這種方法總的目標是將元素分為三部分,0放最前,所以遇到0,得和前面交換位置,遇到2得和後面交換位置,而遇到1,begin儲存不動,cursor向前演化,如此可保證0在前面部分,2在後面部分,而1夾在中間。3.統計法:逐步檢查數組,統計 0 1 2出現的次數,然後再向數組按順序寫入對應次數的值,也可到達目的。時間複雜度也是O(n),但相比劃分法多會多一個常量因子,因為這裡需兩次遍曆數組。