1045 快速排序 (25 point(s))
阿新 • • 發佈:2021-09-01
#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” 那題比較相似,所以就試了下用當時那個迴圈標記並記錄的方法。然後蒙對了。除了有一個意料之外的格式錯誤。
測試點二 Presentation Error,當時還以為是我思路有問題,結果有誤。結果參考別人的一看,這個是格式問題。因為平時都是結果錯太多了,看到紅色的下意識都以為是結果錯了,沒想到原來只是格式錯誤。
以後有必要積累下OJ系統的評測反饋英語的意思是什麼。
還有,結合本題卡測試點,跟前一題 “火星數字” 做一個比較,發現大多數題目卡測試點主要在於某些邊界上。最常見是 0 的時候,這一個題和前一題都出現了。或者是最大元素時候的情況,“火星數字”那就有一個低位最高時候進位的問題。
或者是某些樣例中偷偷給出的特殊條件,還是“火星數字”,因為13進位制,13的倍數都是高位,都要特殊處理。
所以以後卡測試點的時候可以往這些邊界, 或者特殊情況考慮。
看別人還有一種方法將排好序的序列與原序列比較,且當前元素大於左邊元素的最大值。
因為如果不滿足大於左邊的條件(判斷右邊應該也可以),比如
5 4 3 2 1(排序前)
|
1 2 3 4 5(排序後)
可以看到,有可能是序列存在左邊大於右邊的情況,在排序後剛好左右調換了位置。這確實能夠滿足元素排序後位置不變,但是不能滿足題目的條件,“主元小的元素放到它的左邊,比主元大的元素放到它的右邊”。
演算法筆記裡面提到了,該題和幾個PAT的題目都可以用到一個遞推的方法,即通過預處理標記元素左右的資料,再處理。