1. 程式人生 > >PAT-BASIC1045——快速排序

PAT-BASIC1045——快速排序

題目描述:

知識點:快速排序

思路:先排序,尋找和排序後陣列相同的數字

對於快排而言,題目所述的主元的位置就是其排序後的最終位置

所以如果該元素是主元,那麼一定滿足其位置和排序後的陣列中的位置相同。但是僅僅滿足這一點是不夠的,對於[3, 2, 1]這樣的序列,2的位置就是排序後的最終位置,但2並不是一個主元。我們還需滿足一個條件:對於索引為i的主元,陣列中索引在[0, i - 1]位置的最大值需要小於索引在i位置的值

這個條件很容易用反證法證明。假設索引為i的位置不是一個主元。根據條件,[0, i - 1]位置的值均小於i位置的值,那麼i之後的索引一定存在小於i位置的值。但是根據最開始的條件,該位置和排序後的陣列中的位置相同。所以比i小的值有且僅有i個,恰好等於[0, i - 1]中的元素數量,所以i之後的索引不可能小於i位置的值。得出矛盾。所以滿足這兩個條件,就是主元。

時間複雜度是O(nlogn),其中n為輸入的陣列大小。空間複雜度是O(m),其中m為可能的主元數。

本題有一個坑點:

當主元數為0時,需要輸出一個空行,否則測試點2會報格式錯誤。

錯誤思路

我一開始的思路是從頭和從尾分別比較排序後的陣列和輸入陣列中的元素是否相等,將相等的元素看作是主元,一旦發現不相等的元素就停止搜尋。但是我這麼做忽略了這麼一種情況[1, 3, 2, 4, 6, 5, 7],根據我的思路我只能得到[1, 7]是主元,而忽略了主元4。測試點5就是這樣一組測試用例。

C++程式碼:

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

int main() {
	int count;

	cin >> count;

	long tempNum;
	vector<long> beforeSort;
	vector<long> afterSort;
	vector<long> result;

	for (int i = 0; i < count; i++) {
		cin >> tempNum;
		beforeSort.push_back(tempNum);
		afterSort.push_back(tempNum);
	}

	sort(afterSort.begin(), afterSort.end());

	int max = 0;
	for (int i = 0; i < afterSort.size(); i++) {
		if (afterSort[i] == beforeSort[i] && afterSort[i] > max) {
			result.push_back(afterSort[i]);
		}
		if (beforeSort[i] > max) {
			max = beforeSort[i];
		}
	}

	cout << result.size() << endl;
	for (int i = 0; i < result.size(); i++) {
		cout << result[i];
		if (i != result.size() - 1) {
			cout << " ";
		}
	}
	printf("\n");
}

C++解題報告: