Bootstrap

PAT basic 1045 快速排序 (25分) 测试点 2 3 5 错误原因及解决方法

一、题目描述

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

例如给定 N = 5 N = 5 N=5, 排列是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

二、代码

//1045
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

int main()
{
	int n;
	long temp;
	scanf("%d", &n);
	vector<long>a;
	vector<long>b;
	vector<long>re;
	for (int i = 0; i < n; i++)
	{
		scanf("%ld", &temp);
		a.push_back(temp);
		b.push_back(temp);
	}

	sort(b.begin(), b.end());
	long max = 0;
	for (int i = 0; i < n; i++)
	{
		/*if (a[i] == b[i])
			if(re.size()==0 || re[re.size() - 1] != a[i])
				re.push_back(a[i]);
		测试点2 3 5 错误,如果左右并不符合,但碰巧位置相同是不行的
		*/
		if (a[i] == b[i] && a[i] > max)
			re.push_back(a[i]);
		if (a[i] > max)
			max = a[i];
	}

	cout << re.size() << endl;
	if (re.size() != 0)
		printf("%ld", *re.begin());
	if(re.size() > 1 )
		for (auto it = ++re.begin(); it != re.end(); it++)
		{
			printf(" %ld", *it);
		}
	cout << endl;
	return 0;
}

三、测试点错误原因及解释

  • 关于超时问题:
    一开始我的做法时,进行双重循环,分别比较,然而会超时。这也从通过后的样例大小可以推断出来,输入的数组其实是很大的,故如果使用的双重循环是一定会超时的。
  • 关于测试点2 3 5
    测试点2 的格式问题很多博主的文章都提到了,需要输出一个单独的空行
    测试点2 3 5 都会考察一个问题这是我第一次没有考虑到的,就是碰巧位置相同,我发现了如果符合正确的顺序的话位置应该不变,同时考虑的是如果相同的多个数字不应该被多次计算,但忽略了左右不符合的数字数量相等的情况

比如输入:
5
5 4 3 2 1
错误输出:
1
3

所以,加入了记录左侧最大值的项,就通过了

题目合集

在这里呦~

;