1045 快速排序

著名的快速排序算法里有一个经典的划分过程:我们通常采用某种方法取一个元素作为主元,通过交换,把比主元小的元素放到它的左边,比主元大的元素放到它的右边。 给定划分后的 N 个互不相同的正整数的排列,请问有多少个元素可能是划分前选取的主元?

例如给定 , 排列是1、3、2、4、5。则:

  • 1 的左边没有元素,右边的元素都比它大,所以它可能是主元;
  • 尽管 3 的左边元素都比它小,但其右边的 2 比它小,所以它不能是主元;
  • 尽管 2 的右边元素都比它大,但其左边的 3 比它大,所以它不能是主元;
  • 类似原因,4 和 5 都可能是主元。

因此,有 3 个元素可能是主元。

输入格式:

输入在第 1 行中给出一个正整数 N(≤10^5); 第 2 行是空格分隔的 N 个不同的正整数,每个数不超过 10^9。

输出格式:

在第 1 行中输出有可能是主元的元素个数;在第 2 行中按递增顺序输出这些元素,其间以 1 个空格分隔,行首尾不得有多余空格。

输入样例:

5
1 3 2 4 5

输出样例:

3
1 4 5

思路:

本题难度稍大,一开始使用暴力循环方法,果然只能通过三个测试用例。

后来需要观察主元的特性:
如果一个元素是主元,首先必须满足:
(1)该元素的位置是正常排序的位置
(2)该元素前的最大元素必须比该元素小。

例如数列:1 3 2 4 5
主元1 4 5的位置与正常排序时1 2 3 4 5的位置是相同的,其次,每一个主元的前面都没有比他大的元素

例如数列: 5 4 3 1 2
数字3虽然与正常排序的位置相同,但是其前面有比他大的元素,因此3不是主元

知道这个规律以后就好处理了:

关键的判断循环如下:

for (int i = 0; i < N; i++)
//要满足为主元,首先需要该元素的位置为排序后的位置
//其次,该元素前的最大元素必须比这个元素小
{
    max = max > store[i] ? max : store[i];//随时存储最大元素
    if (store[i] != tep[i])tep[i] = 0;//如果位置不对,将该元素设为0
    if (max > store[i])tep[i] = 0;//如果前面最大元素比该元素大,将该元素设置为0
    if (tep[i] != 0)result.push_back(tep[i]);//如果该元素没有设为0,证明其是主元,存在result中
}
//其中tep数组是排序后的数组,store是排序前的数组

注意本题还有一个测试点,是如果没有主元需要先输出0,然后输出一个空行。

代码:

快速排序

//1045 快速排序
#include
#include
#include

using namespace std;

int main()
{
    int N;
    cin >> N;//输入元素个数
    int temp, max = 0;//temp用于临时存储数据,max用于存放前面为止的最大数
    vector store, tep, result;
    for (int i = 0; i < N; i++)//将所有元素存在store中
    {
        cin >> temp;
        store.push_back(temp);
    }
    tep = store;
    sort(tep.begin(), tep.end());//对原数组进行排序

    for (int i = 0; i < N; i++)
    //要满足为主元,首先需要该元素的位置为排序后的位置
    //其次,该元素前的最大元素必须比这个元素小
    {
        max = max > store[i] ? max : store[i];//随时存储最大元素
        if (store[i] != tep[i])tep[i] = 0;//如果位置不对,将该元素设为0
        if (max > store[i])tep[i] = 0;//如果前面最大元素比该元素大,将该元素设置为0
        if (tep[i] != 0)result.push_back(tep[i]);//如果该元素没有设为0,证明其是主元,存在result中
    }
    if (result.size() == 0)//如果没有主元,输出0,然后在输出一个空行,这是第三个测试点
    {
        cout << 0 << endl;
        cout << endl;
        return 0;
    }
    else
    {
        cout << result.size() << endl;
        for (unsigned int i = 0; i < result.size() - 1; i++)
        {
            cout << result[i] << ' ';
        }
        cout << result[result.size() - 1] << endl;
    }
    return 0;
}

你可能感兴趣的:(1045 快速排序)