演算法學習-荷蘭國旗問題
題目
問題分析現有紅、白、藍三個不同顏色的小球,亂序排列在一起,請重新排列這些小球,使得紅白藍三色的同顏色的球在一起。
問題轉換為:給定陣列A[0...N-1],元素只能取0、1、2三個值,設計演算法,使得陣列排列成“00...0011...1122...22”的形式
借鑑快速排序中partition的過程,定義三個指標begin=0,current=0,end=N-1
A[cur]==2,則A[cur]與A[end]交換,end--,cur不變
A[cur]==1,則cur++,begin不變,end不變
A[cur]==0,則:
若begin==cur,則begin++,cur++
若begin!=cur,則A[cur]與A[begin]交換,begin++,cur不變
程式碼如下
void Holland1(int* a, int length)
{
int begin = 0;
int current = 0;
int end = length - 1;
while (current <= end)
{
if (a[current] == 2)
{
swap(a[end], a[current]);
end--;
}
else if (a[current] == 1)
{
current++;
}
else
{
if (begin == current)
{
begin++;
current++;
}
else
{
swap(a[current], a[begin]);
begin++;
}
}
}
}
第二個版本:
cur掃過的位置,即:[begin,cur)區間內,一定沒有2
因此:A[begin]要麼是0,要麼是1,不可能是2在前面的A[cur]==2中,已經被替換到陣列後面了
考察begin指向的元素的值:
歸納法:若begin!=cur,則必有A[begin]=1
因此,當A[cur]==0時,
若begin==cur,則begin++,cur++;
若begin!=cur,因為A[begin]==1,則交換後,A[cur]==1,此時,可以cur++;
void Holland2(int* a, int length)
{
int begin = 0;
int current = 0;
int end = length - 1;
while (current <= end)
{
if (a[current] == 2)
{
swap(a[end], a[current]);
end--;
}
else if (a[current] == 1)
{
current++;
}
else
{
if (begin == current)
{
begin++;
current++;
}
else
{
swap(a[current], a[begin]);
begin++;
current++;
}
}
}
}
終極版本
void Holland(int* a, int length)
{
int begin = 0;
int current = 0;
int end = length - 1;
while (current <= end)
{
if (a[current] == 2)
{
swap(a[end], a[current]);
end--;
}
else if (a[current] == 1)
{
current++;
}
else
{
if (current != begin)
{
swap(a[current], a[begin]);
}
begin++;
current++;
}
}
}
荷蘭國旗問題擴充套件
- 將0/1/2分別計數,根據三個計數值c0/c1/c2:前c0個元素賦值為0,中間c1個元素賦值為1,最後c2個元素賦值為2;實際意義比較小,可能排序結構比較複雜的時候就用著不方便了
- 將(0,1)(2)根據快速排序的Partition,劃分為兩部分(如PivotKey1.5);將(0)(1)根據快速排序Partition,分成兩部分(如PivotKey選擇0.5);那麼可以得到結論“兩次Partition==一次荷蘭國旗”,這樣可以優化快速排序的Partition過程
優化快速排序根據PivotKey分成大於、小於等於兩部分或者大於等於、小於兩部分
根據PivotKey的大小,將Partition過程蓋在成大於、等於、小於三部分
優點:對於快速排序的等於PivotKey的數值,可以在執行下一次Partition時直接跳過,利於資料規模的降低
相關文章
- ACM 荷蘭國旗問題ACM
- 彩虹排序 | 荷蘭旗問題排序
- 荷蘭國旗問題引出的三色排序排序
- 高頻面試考題:荷蘭旗問題面試
- 在連結串列上實現 Partition 以及荷蘭國旗問題
- 迴圈不變數之荷蘭國旗變數
- 演算法學習之路|日期問題演算法
- 演算法學習回顧-皇后問題演算法
- 演算法學習之路|棋盤問題(博弈)演算法
- 【演算法學習筆記】生成樹問題探究演算法筆記
- react 學習 問題React
- Spark學習——問題排查Spark
- 學習方向的問題
- 面經問題學習
- 基礎學習問題
- 國際象棋“皇后”問題的回溯演算法演算法
- 【CSS】孟加拉共和國國旗CSS
- 演算法學習之路|選擇題演算法
- JERSEY學習遇到的問題
- mysql學習整理所有問題MySql
- 學習redis問題記錄Redis
- 【學習】分享幾個學習中的小問題
- 荷蘭推出國家區塊鏈研究計劃區塊鏈
- iOS面試旗開得勝之問題篇iOS面試
- 紅旗linux 雙機問題解決Linux
- java學習中不懂的問題Java
- 淺談深度學習落地問題深度學習
- weex學習中遇到的問題
- Session重疊問題學習(一)Session
- 解決問題oracle學習篇Oracle
- hive學習中遇到的問題Hive
- 請教banq DDD學習問題!
- 【DATAGUARD 學習】學習DATAGUARD 過程中遇到的問題
- Session重疊問題學習(九)--該問題第七次優化.優化合並演算法Session優化演算法
- 【演算法習作】中國象棋將帥問題演算法
- 【求助】安裝紅旗4.1時遇到問題!!!!(轉)
- 強化學習-學習筆記11 | 解決高估問題強化學習筆記
- 一道趣味數學演算法問題演算法