荷蘭國旗問題

時間: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),但相比劃分法多會多一個常量因子,因爲這裏需兩次遍歷數組。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章