算法面試題,在數組中找出這樣的數,它比它前面的數都大,比它後面的數都小

問題:在一個數組A[n]中,找出所有這樣的A[i],它比它前面的所有數都要大,比它後面的數都要小
例如:如果A[8] = {1 2 3 4 5 6 7 8},則輸出 1 2 3 4 5 6 7 8
            如果A[8] = {8 7 6 5 4 3 2 1},則輸出爲空

            如果A[8] = {3 5 4 2 1 6 8 7},則輸出爲6

這裏給出四種方法,所有方法中,beg指向數組第一個元素,end指向數組中最後一個元素。

方法一:暴力搜索法

對每一個元素,判斷它是否比它前面的數都大,然後判斷它是否比它後面的數都小

void ViolentWay(int *beg, int *end){
	if(beg == end){
		cout<<*beg<<end;
		return;
	}
	int *cur;
	for(cur = beg; cur<=end; ++cur){
		int *temp;
		for(temp = beg; temp<cur; ++temp){<span style="white-space:pre">	</span>//與前面的數進行比較
			if(*temp > *cur){
				break;
			}
		}
		if(temp != cur){<span style="white-space:pre">	</span>// 如果是中途break出來的,則 temp!=cur ,這時要continue,對下一個數進行判斷
			continue;
		}
		for(temp=cur+1; temp<end+1; ++temp){<span style="white-space:pre">	</span>// 與後面的數進行比較
			if(*temp < *cur){
				break;
			}
		}
		if(temp == end+1){<span style="white-space:pre">	</span>// 兩個循環安全走完,複合要求
			cout<<*cur<<' ';
		}
	}
	cout<<endl;
}
方法二:排序輔助法

這種方法不可行,請直接忽略!!!

對於原先的數組A[n],申請一個新的數組B[n],B[n]存放A[n]排序後的結果。對應位置上A[i]==B[i],則輸出。

void SortWay(int *beg, int *end){
	if(beg == end){
		cout<<*beg<<end;
		return;
	}

	int Size = end-beg+1;
	int *Low = new int[Size];<span style="white-space:pre">	</span>// 申請內存空間
	int *High = Low;

	int *temp;
	for(temp=beg; temp<=end; ++temp){<span style="white-space:pre">	</span>// 數組複製
		*High++ = *temp;
	}
	sort(Low, High);<span style="white-space:pre">		</span>// 排序

	for(temp=beg, High=Low; temp<=end; ++temp,High++){
		if(*temp == *High){
			cout<<*temp<<' ';
		}
	}
	cout<<endl;
	delete[] Low;
}
方法三:“查找表”法

構造一個“查找表” Min[n];對應位置上Min[i],存放了原數組A[i]位置往後這一部分的最小值。

一個變量Max,保存了在遍歷A[n]時,遇到的最大值。

遍歷A[n],如果 A[i]>=Max (比前面的數都大),並且 A[i] <= Min[i] (比後面的數都小),輸出A[i].

void LookupWay(int *beg, int *end){
	if(beg == end){
		cout<<*beg<<end;
		return;
	}

	int Size = end-beg+1;
	int *Min = new int[Size];
	int *pcur, *pM;

	*(Min+Size-1) = *end;
	for(pcur=end-1, pM=Min+Size-2; pcur>=beg; --pcur, --pM){
		*pcur<*(pM+1)? *pM=*pcur : *pM=*(pM+1);		// 構造“查找表”
	}

	int Max=*beg;
	for(pcur=beg, pM=Min; pcur<=end; ++pcur, ++pM){
		if(*pcur > Max){					// 修改“當前對象前面部分的最大值”
			Max = *beg;
		}
		if(*pcur >= Max && *pcur <= *pM){		// 判斷是否符合條件
			cout<<*pcur<<' ';
		}
	}
	cout<<endl;

	delete[] Min;
}

四:快速搜索法

在數組中,找到最小值的地址(指針、索引)MinIndex,則

1、如果MinIndex 指向最後一個元素,則原數組中所有元素均不滿足,return;

2、如果MinIndex 指向第一個元素,則第一個元素滿足要求,輸出。

3、如果MinIndex 指向中間的某個元素,則對後半部分,遞歸進行上面的過程。

在上述算法中,需要設置一變量Max,保存MinIndex 前面一部分的最大值。

下面是算法的實現,已經將遞歸算法改爲循環了。

int *FindMax(int *beg, int *end){
	int *Index = beg;
	int *temp;
	for(temp = beg; temp <=end; ++temp){
		if(*temp >= *Index){
			Index = temp;
		}
	}
	return Index;
}
int *FindMin(int *beg, int *end){
	int *Index = beg;
	int *temp;
	for(temp = beg; temp <=end; ++temp){
		if(*temp <= *Index){
			Index = temp;
		}
	}
	return Index;
}
void QuickWay(int *beg, int *end, int Max=0xf0000000){<span style="white-space:pre">	</span>//Max 最大值初始化爲最大負數值
	if((beg == end)&&(*beg >= Max)){
		cout<<*beg<<endl;
		return;
	}	
	int *MaxIndex, *MinIndex;
	while(true){
		MinIndex = FindMin(beg,end);<span style="white-space:pre">		</span>// 找到最小值的索引
		MaxIndex = FindMax(beg, MinIndex);<span style="white-space:pre">	</span>// 找到MinIndex 前面一部分的最大值
		if(*MaxIndex > Max){
			Max = *MaxIndex;
		}
		if(end == MinIndex ){<span style="white-space:pre">			</span>// MinIndex 指向最後一個元素時,就可以break了,但最後一個元素也可能符合要求
			if(*end >= Max){
				cout<<*end;
			}
			break;
		}
		else if((beg == MinIndex)&&(*MinIndex >=Max)){<span style="white-space:pre">		</span>// MinIndex 指向第一個元素,如果它比Max大,則符合要求
			cout<<*MinIndex<<' ';
		}
		beg = MinIndex + 1;
	}
	cout<<endl;
}

方法 空間複雜度 時間複雜度(最好) 時間複雜度(平均) 時間複雜度(最壞)
暴力搜索 O(1) O(N^2) O(N^2) O(N^2)
排序輔助法 O(N) O(N) O(NlogN) O(N^2)
查找表 O(N) O(N) O(N) O(N)
快速搜索 O(1) O(N) O(NlogN) O(N^2)




發佈了29 篇原創文章 · 獲贊 32 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章