同時找到最大值和最小值——程式設計之美

bigface1234fdfg發表於2015-02-03

同時找到最大值和最小值——程式設計之美

    

    給定一個陣列,我們可以同時找到其中的最大數和最小數嗎?要求時間複雜度儘可能的小。


程式設計之美上面提供了三個思路,我把它們都實現了,並做一些講解補充。


    思路一:


兩次遍歷,分別得到最大值和最小值。時間複雜度為O(2*N)。


    思路二:


把最前面的兩個數作為最值的候選,然後後面的數兩兩一組,分別讓其中的較大值和候選最值比較,讓其中的較小值和候選最值比較。

    感覺這種方法和推排序有點兒類似。。


    思路三:


採用分治法思想,把整個陣列一分為二,讓左邊的最值和右邊的最值分別比較,這裡有個遞迴的過程,主要跳出遞迴的條件是當陣列的begin和end相差小於等於1的時候,跳出。


    上面三個思路的程式碼如下:


#include<iostream>
using namespace std; 

struct Pair
{
	int max, min; 
};

// 遍歷兩次,時間複雜度為O(2*N)
Pair minMax_1(int a[], int n)
{
	int max = a[0], min = a[0]; 

	for(int i = 0; i < n; i++)
	{
		min = a[i] < min ? a[i]:min; 
		max = a[i] > max ? a[i]:max; 
	}

	Pair p; 
	p.max = max; 
	p.min = min; 

	return p; 
}

// 兩兩比較,時間複雜度是O(1.5*N)
Pair minMax_2(int a[], int n)
{
	int max = a[0], min = a[1]; 
	if(max < min)
		swap(max, min); 

	for(int i = 2; i < n; i = i + 2)  // 遞進2個
	{
		int tmpMin = a[i]; 
		int tmpMax = a[i+1]; 
		if(tmpMax < tmpMin)
			swap(tmpMin, tmpMax);   // 候選

		max = max > tmpMax ? max:tmpMax; 
		min = min < tmpMin ? min:tmpMin; 
	}

	// 防止長度為奇數
	max = max > a[n-1] ? max:a[n-1]; 
	min = min < a[n-1] ? min:a[n-1]; 	

	Pair p; 
	p.max = max; 
	p.min = min; 

	return p; 
}

// 分治法,時間複雜度也是O(1.5*N)
Pair minMax_3(int a[], int begin, int end)
{
	Pair P; 
	if(end - begin <= 1)
	{
		P.max = a[begin] > a[end] ? a[begin]:a[end]; 
		P.min = a[begin] < a[end] ? a[begin]:a[end]; 
		return P; 
	}

	Pair PL = minMax_3(a, begin, begin + (end - begin) / 2); 
	Pair PR = minMax_3(a, begin + (end - begin) / 2 + 1, end); 
	P.max = PL.max > PR.max ? PL.max:PR.max; 
	P.min = PL.min < PR.min ? PL.min:PR.min; 

	return P; 
}

int main()
{
	Pair P; 
	int a[] = {3, 6, 1, 8, 0}; 
	int n = 5; 

	// solution 1 
	P = minMax_1(a, n); 
	cout<<P.min<<' '<<P.max<<endl; 

	//solution 2
	P = minMax_2(a, n); 
	cout<<P.min<<' '<<P.max<<endl; 

	//solution 3
	P = minMax_3(a, 0, n-1); 
	cout<<P.min<<' '<<P.max<<endl; 

	return 0; 
}



相關文章