題目描述:
著名的快速排序演算法裡有乙個經典的劃分過程:我們通常採用某種方法取乙個元素作為主元,通過交換,把比主元小的元素放到它的左邊,比主元大的元素放到它的右邊。 給定劃分後的n個互不相同的正整數的排列,請問有多少個元素可能是劃分前選取的主元?
例如給定n = 5, 排列是1、3、2、4、5。則:
1的左邊沒有元素,右邊的元素都比它大,所以它可能是主元;
儘管3的左邊元素都比它小,但是它右邊的2它小,所以它不能是主元;
儘管2的右邊元素都比它大,但其左邊的3比它大,所以它不能是主元;
類似原因,4和5都可能是主元。
因此,有3個元素可能是主元。
輸入格式:
輸入在第1行中給出乙個正整數n(<= 105); 第2行是空格分隔的n個不同的正整數,每個數不超過109。
輸出格式:
在第1行中輸出有可能是主元的元素個數;在第2行中按遞增順序輸出這些元素,其間以1個空格分隔,行末不得有多餘空格。
輸入樣例:
5 1 3 2 4 5
輸出樣例:
3 1 4 5
題目分析:
這道題目如果暴力解題,毫無疑問時間複雜度會很高,那麼我們就要想辦法來降低程式執行的次數。
熟悉的快速排序的讀者應該知道,快速排序每選擇一次的主元進行一輪排序之後,主元的位置就是最終的位置。那麼我們可以利用這個特點排除掉一大部分的無用計算。即直接使用sort得到最終的序列,然後核對前後的位置有沒有發生變化,變化的一定不可能是主元。但是位置沒有變化的也有一些不時主元,比如序列 1 4 3 2 5 中的3雖然位置沒有變化,但是前面有比它大的4,所以它也不可能是主元。所以我們還需要多加一部判斷。筆者是一開始就設定的結構體,成員位:記錄初始位置的location,記錄資料的num,以及標記初始序列的該元素是不是都比它之前元素大的flag。
另外注意的是:測試點2的格式,很容易就能實驗猜到測試點2的資料主元個數為零,但是輸出主元的位置仍然要流出來,就是在最後在加一句printf(「\n」);
請看下面**:
#include
#include
using
namespace
std;
const
int maxn=100001;
struct numberdata[maxn];
bool cmp(number a,number b)
data[i].location=i; //記錄初始位置
}sort(data,data+n,cmp); //排序
for(int i=0;iif(data[i].location==i&&data[i].flag)
}
printf("%d\n",count); //輸出主元個數
for(int i=0;iif(data[i].location==i && data[i].flag )
else
printf(" %d",data[i].num ); //之後的每乙個主元前都要輸出空格 }}
printf("\n"); //不加這一句,測試點2過不去
}
PAT1045 快速排序 25
題目思路 1.初步我用迴圈做的,發現超時 2.思路改進,觀察給出的樣例和他的輸出 1 3 2 4 5 排序後 1 2 3 4 5 要的結果 1 4 5 是不是有點感覺了呢 3.我就按照這個思路又複製了原來的陣列,將原來的陣列排序後,遍歷對比一下,找到位置相同的,count 4.滿懷好奇,成功了幾個,...
PAT 1045 快速排序
著名的快速排序演算法裡有乙個經典的劃分過程 我們通常採用某種方法取乙個元素作為主元,通過交換,把比主元小的元素放到它的左邊,比主元大的元素放到它的右邊。給定劃分後的n個互不相同的正整數的排列,請問有多少個元素可能是劃分前選取的主元?例如給定n 5,排列是1 3 2 4 5。則 1的左邊沒有元素,右邊...
PAT 1045 快速排序
1045 快速排序 25 分 著名的快速排序演算法裡有乙個經典的劃分過程 我們通常採用某種方法取乙個元素作為主元,通過交換,把比主元小的元素放到它的左邊,比主元大的元素放到它的右邊。給定劃分後的 n 個互不相同的正整數的排列,請問有多少個元素可能是劃分前選取的主元?例如給定 n 5 n 5 n 5,...