1. 程式人生 > >荷蘭國旗演算法及其拓展

荷蘭國旗演算法及其拓展

一排木桶裡分別裝有紅白藍三色小球(分別用0,1,2表示),如何讓所有的'0'出現在前面,所有的'1'在中間,所有的'2'在最後。
要求:要求空間複雜度為O(1),只許遍歷一遍字串陣列。 
之所以叫荷蘭國旗,是因為我們可以將紅白藍三色小球想象成條狀物,有序排列後正好組成荷蘭國旗。
該演算法的精髓在於把元素分為3個區域,只需掃描一次,通過交換元素,就能把元素放到該去的區域。 

我們可以把該演算法擴充套件到將COLORNUM個不同顏色的小球(數字)按順序歸類,只需要不斷地把左右邊界往中間移動就行。 

#include <iostream>
#include <cstdlib>

using namespace std;

void Sort(int lib[], int libLen, int color[], int colorLen);
void TheDutchFlag(int lib[], int &left, int &right, int min, int max);
void Swap(int &a, int &b);

int main()
{
	const int COLORNUM = 19;
	int color[COLORNUM] = {0};
	
	for (int i=0; i<COLORNUM; i++) //為不同顏色賦值 
	{
		color[i] = i;
	}
	
	const int MAXSIZE = 140;
	int lib[MAXSIZE] = {0};
	
	for (int i=0; i<MAXSIZE; i++)
	{
		lib[i] = rand() % COLORNUM;
	}
	
	for (int i=0; i<MAXSIZE; i++)
	{
		cout << lib[i] << " ";
	}
	cout << endl;

   Sort(lib, MAXSIZE, color, COLORNUM);
	
	for (int i=0; i<MAXSIZE; i++)
	{
		cout << lib[i] << " ";
	}
	cout << endl;
    
    return 0;
}

void Swap(int &a, int &b)
{
	int temp = a;
	a = b;
	b = temp;
}

void Sort(int lib[], int libLen, int color[], int colorLen)//將COLORNUM個不同顏色的小球(數字)按順序歸類
{
	int left = 0;
	int right = libLen - 1;
	int min = 0;
	int max = colorLen - 1;
	
	while (min < max && left < right)
	{
		if (min == max - 1) //只有兩個不同元素,直接交換即可
		{
			while (left < right)
			{
				while (lib[left] == color[min]) //確定左邊界的位置 
				{
					left++;
				}
				
				while (lib[right] == color[max]) //確定右邊界的位置 
				{
					right--;
				}
				
				if (left < right)
				{
					Swap(lib[left++], lib[right--]);
				}
			}
		} 
		else //有超過2個不同元素,先把最大值和最小值分別放到左右區域,其他元素放在中間區域 
		{
			TheDutchFlag(lib, left, right, color[min], color[max]);
		}
		//處理中間的區域的元素,重新設定最大值和最小值 
		min++;
		max--;
	}
}

void TheDutchFlag(int lib[], int &left, int &right, int min, int max)
{
	while (lib[left] == min) //確定左邊界的位置 
	{
		left++;
	}
		
	while (lib[right] == max) //確定右邊界的位置 
	{
		right--;
	}
		
	int i = left;
	while (i <= right)
	{
		if (lib[i] == min) //是最小值,則與左區域的元素交換,同時左邊界右移,遊標也右移 
		{
			Swap(lib[i++], lib[left++]);
		}
		else if (lib[i] == max) //是最大值,則與右區域的元素交換,同時右邊界左移,遊標不動 
		{
			Swap(lib[i], lib[right--]);
		}
		else //既不是最大值也不是最小值,則該元素屬於中間區域,不做任何交換,遊標右移 
		{
			i++;
		}
	}
}


相關推薦

荷蘭國旗演算法及其拓展

一排木桶裡分別裝有紅白藍三色小球(分別用0,1,2表示),如何讓所有的'0'出現在前面,所有的'1'在中間,所有的'2'在最後。 要求:要求空間複雜度為O(1),只許遍歷一遍字串陣列。 之所以叫荷蘭國旗,是因為我們可以將紅白藍三色小球想象成條狀物,有序排列後正好組成荷蘭國旗

快速冪演算法及其拓展

摘要 本文講解了快速冪演算法的定義、複雜度證明及兩種實現(遞迴與非遞迴),以及它的兩個重要拓展:快速冪模M演算法和矩陣快速冪。其中矩陣快速冪演算法是矩陣求冪問題對整數求冪問題的借鑑,實際應用中對於線性遞推式求解能起到強大的效率優化。 快速冪演算法

雜湊演算法及其拓展

本篇是iOS逆向開發的遞進篇-關於雜湊演算法、數字簽名及對稱加密等,下面我們著重講解此內容,希望對大家有所幫助!!!    一、雜湊 1.1 基本內容 雜湊表也稱為散列表(Hash table),是根據關鍵碼值(key,value),直接進行訪問的資料結構。通過把關鍵碼對映到表中的一個位置

演算法初級02——荷蘭國旗問題、隨機快速排序、堆排序、桶排序、相鄰兩數的最大差值問題、工程中的綜合排序演算法

主要討論:荷蘭國旗問題、隨機快速排序、堆排序、穩定性、比較器、桶排序、相鄰兩數的最大差值問題和簡單介紹工程中的綜合排序演算法   題目一 給定一個數組arr,和一個數num,請把小於等於num的數放在陣列的左邊,大於num的數放在陣列的右邊。 要求額外空間複雜度O(1),時間複雜度O(N)

面試常考演算法題(二)--荷蘭國旗問題

面試常考演算法題(二)–荷蘭國旗問題 荷蘭國旗問題是面試中常考的一個題目,涉及到的思想並不是很複雜. 荷蘭國旗問題 題目 給定一個數組arr,和一個數num,請把小於num的數放在陣列的左邊,等於num的數放在陣列的中間,大於num的數放在陣列的右邊。 要求

演算法之(一)荷蘭國旗問題

通過一次劃分,將陣列分為三部分,前半段為小於num的數,中間半段為等於num的數,後半段為大於num的數 public static void partition(int[] arr, int num) { int less = -1; int more

演算法初級02——荷蘭國旗問題、隨機快速排序、堆排序

public static void heapSort(int[] arr) { if (arr == null || arr.length < 2) { return; } for (int i = 0; i <

左神演算法課程系列--荷蘭國旗問題

code技巧的磨練 【題目】 荷蘭國旗問題 已知一個整型陣列arr,和一個整數num,請把小於num的數放在陣列的左邊,等於num的數放在陣列的中間,大於num的數放在陣列的右邊。要求:時間複雜度為O(N),額外空間複雜度O(1)。 這個題目應該很多人是想到排序的,但排序的

求解最大公約數——歐幾里得演算法及其(解同餘方程)拓展歐幾里得

/* 擴充套件歐幾里得定理 擴充套件歐幾里得定理:對於兩個不全為0的整數a、b,必存在一組解x,y, 使得ax+by==gcd(a,b); 拓展歐幾里得實現 下面面的程式中,x和y用全域性變數儲存 int gcd(int a,int b) { int t,d; if

編程之法:面試和算法心得(荷蘭國旗

數組排列 alt partition void 不同 begin 心得 不能 sta 內容全部來自編程之法:面試和算法心得一書,實現是自己寫的使用的是java 題目描述 拿破侖席卷歐洲大陸之後,代表自由,平等,博愛的豎色三色旗也風靡一時。荷蘭國旗就是一面三色旗(只不過是橫向

75. Sort Colors(荷蘭國旗問題 三指針)

resp order 問題 row them clas pre spa use Given an array with n objects colored red, white or blue, sort them so that objects of the

中國剩余定理及其拓展

align 孫子兵法 bubuko 線性同余方程組 轉化 sub prim 未知數 min 中國剩余定理及其拓展 中國剩余定理CRT引例:(選自孫子兵法) 今有物不知其數,三三數之剩二,五五數之剩三,七七數之剩二,問物幾何? 怎麽考慮這個問題? 按照題意: 設答案

圖論初步-Tarjan演算法及其應用

暑假刷了一堆Tarjan題到頭來還是忘得差不多。 這篇部落格權當複習吧。 一些定義 無向圖 割頂與橋 (劃重點) 圖G是連通圖,刪除一個點表示刪除此點以及所有與其相連的邊。 若刪除某點u後G不再連通,那麼u是G的一個割頂(割點)。 若刪除某邊e後G不再連通,那麼e是G的一個橋。 雙連通 一個圖為雙

資料結構(二):演算法及其描述

一、演算法及其描述 1、什麼是演算法 資料元素之間的關係有邏輯關係和物理關係,對應的操作有邏輯結構上的操作功能和具體儲存結構上的操作實現。 把 具體儲存結構上的操作實現方法 稱為演算法。 確切地說,演算法是對特定問題求解步驟的一種描述,它是指令的有限序列,其中每一

菜鷄日記——KMP演算法及其優化與應用

一、什麼是KMP演算法 KMP演算法,全稱Knuth-Morris-Pratt演算法,由三位科學家的名字組合命名,是一種效能高效的字串匹配演算法。假設有主串S與模式串T,KMP演算法可以線上性的時間內匹配出S中的T,甚至還能處理由多個模式串組成的字典的匹配問題。 二、KMP演算法原理及實現

Round-Robin負載均衡演算法及其實現原理

輪詢排程演算法(Round-Robin Scheduling) 輪詢排程演算法的原理是每一次把來自使用者的請求輪詢分配給內部中的伺服器,從1開始,直到N(內部伺服器個數),然後重新開始迴圈。 演算法的優點是其間接性,它無需記錄當前所有連線的狀態,所以它是一種無狀態排程。 輪詢排程演算法流

MDS演算法及其matlab實現

問題背景: 在求解MTSP問題的時候,因為已知的為各個巡檢點之間路徑耗時長度,而這個具體描述採用無向圖結構可以很好的描述,在matlab中通過函式(graphallshortestpaths)可以得到任意兩個巡檢點之間的距離矩陣 1 %%得到任意兩個巡檢點之間的路徑時間長度 2 %W表示從一個巡

EM演算法及其理解

1. EM演算法是求解含有隱變數的極大似然估計引數的迭代演算法。 2. 極大似然估計可以用梯度下降法求解,但是如果概率分佈中含有隱變數的時候,先求和再求log,再求導很難。 3. 對於每一輪的迭代,先找到當前函式的一個下界函式,如果我們找到讓下界函式達到最大的引數,那麼這個引數也

演化演算法及其衍生演算法的主要思想

…/lib/libcaffe.so.1.0.0: undefined reference to leveldb::DB::Open(leveldb::Options const&, std::string const&, leveldb::DB**)' ../lib/libc

C++基礎-分支條件if語句及其拓展

前言:從這節課開始,接觸到的程式設計知識就要從簡單的計算一個表示式或者輸出一些圖形轉入到計算機邏輯運算的範圍。這是一個相對輕鬆,但其實有很容易被忽視的環節,我們在以後的學習中,更多需要模擬計算機的執行過程,從而推導一個結果,而要模擬程式的執行過程,就需要明白程式的執行順序。而本節課的課程