1. 程式人生 > 其它 >1045 快速排序 (25 point(s))

1045 快速排序 (25 point(s))

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f 
using namespace std;

int main() {
	// 取主元 左小右大 判斷主元個數
	int n, a[100000], b[2][100000], max = 0, min = INF;
	set<int> result;
	cin >> n;
	
	for (int i = 0; i < n; i++){
		cin >> a[i];
	}
	
	// 順序遍歷一邊 記錄左邊每個下標位置的最大元素
	for (int i = 0; i < n; i++){
		
		if(a[i] > max){
			max = a[i];
		}
		b[0][i] = max;
	}
	
	// 逆序遍歷 比較右邊最小元素並記錄 
	for (int i = n-1 ; i >= 0; i--){
		if(a[i] < min){
			min = a[i];
		}
		b[1][i] = min;
		
		// 比較當前元素 左右最值
		// 大於等於左邊最大值 小於等於右邊最小值 加入主元 
		if(b[0][i] <= a[i] && a[i] <= b[1][i]){
			result.insert(a[i]);
		} 
	}
	if(result.size()) 
		cout << result.size() << endl;
	// 測試點二 沒有元素需要輸出多一個空行 
	else
		cout << result.size() << endl << endl;
		
	int flag = 0;
	for(auto r : result)
		cout << ( flag++ ? " " : "") << r;
}

當時想的時候感覺跟前不久寫的 “有幾個PAT” 那題比較相似,所以就試了下用當時那個迴圈標記並記錄的方法。然後蒙對了。除了有一個意料之外的格式錯誤。

有幾個PAT


測試點二 Presentation Error,當時還以為是我思路有問題,結果有誤。結果參考別人的一看,這個是格式問題。因為平時都是結果錯太多了,看到紅色的下意識都以為是結果錯了,沒想到原來只是格式錯誤。

以後有必要積累下OJ系統的評測反饋英語的意思是什麼。

測試點二參考

常見的OJ評測結果


還有,結合本題卡測試點,跟前一題 “火星數字” 做一個比較,發現大多數題目卡測試點主要在於某些邊界上。最常見是 0 的時候,這一個題和前一題都出現了。或者是最大元素時候的情況,“火星數字”那就有一個低位最高時候進位的問題。

或者是某些樣例中偷偷給出的特殊條件,還是“火星數字”,因為13進位制,13的倍數都是高位,都要特殊處理。

所以以後卡測試點的時候可以往這些邊界, 或者特殊情況考慮。


看別人還有一種方法將排好序的序列與原序列比較,且當前元素大於左邊元素的最大值。

因為如果不滿足大於左邊的條件(判斷右邊應該也可以),比如

5 4 3 2 1(排序前)
    | 
1 2 3 4 5(排序後)

可以看到,有可能是序列存在左邊大於右邊的情況,在排序後剛好左右調換了位置。這確實能夠滿足元素排序後位置不變,但是不能滿足題目的條件,“主元小的元素放到它的左邊,比主元大的元素放到它的右邊”。

參考程式碼


演算法筆記裡面提到了,該題和幾個PAT的題目都可以用到一個遞推的方法,即通過預處理標記元素左右的資料,再處理。