PAT乙级1045 快速排序///理解快排后的巧妙做法///考虑极端情况

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

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

输入格式:
输入在第 1 行中给出一个正整数 N(≤105); 第 2 行是空格分隔的 N 个不同的正整数,每个数不超过 10​9
输出格式:
在第 1 行中输出有可能是主元的元素个数;在第 2 行中按递增顺序输出这些元素,其间以 1 个空格分隔,行首尾不得有多余空格。

输入样例:
5
1 3 2 4 5
输出样例:
3
1 4 5

思路:这题我本身无从下手,后来参考了别人的代码才发现是自己对快排的理解不够深导致的。快排寻找一个主元,交换后主元左边的都比主元小,右边都比主元大。而现在题目要求我们在一串数字中寻找一个主元,并满足上述条件。我们可以理解成:题目已经帮我们完成了寻找主元并交换的过程。也就是说,按照快排的步骤,接下来就该将主元左右两边的数分别调用递归进行进行快排。这暗示我们一个很重要的信息:第一个主元已经归位了,已经摆放在了有序数组中他应该在位置。
所以做法先将数字列入数组vec1中,然后复制一个数组vec2,将vec2进行排序再逐个与vec1比较,相等则说明是主元(×)
于是第一次写的代码如下:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
	int n;
	bool flag = false;
	cin >> n;
	vector<int> vec1, vec2, vec3;
	for (int i = 0; i < n; i++)
	{
		int num;
		cin >> num;
		vec1.push_back(num);
		vec2.push_back(num);
	}
	sort(vec2.begin(), vec2.end());
	for (int i = 0; i < vec1.size(); i++)
		if (vec1[i] == vec2[i])
			vec3.push_back(vec1[i]);
	sort(vec3.begin(), vec3.end());
	cout << vec3.size() << endl;
	for (int i = 0; i < vec3.size(); i++)
	{
		if (i != 0) cout << ' ';
		cout << vec3[i];
	}
	return 0;
}

然而这段代码只能通过4个样例,随后发现之前说的“相等则说明是主元”比较片面,有一个极端的例子比如:54321,复制数组并排序后发现3是相等的,可是3不满足左边都比他小,右边都比他大的情况。所以要在条件上再加一条,“相等,且左边的最大值都比他小,则说明是主元”
更改后代码如下:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
	int n;
	bool flag = false;
	cin >> n;
	vector<int> vec1, vec2, vec3;
	for (int i = 0; i < n; i++)
	{
		int num;
		cin >> num;
		vec1.push_back(num);
		vec2.push_back(num);
	}
	int MAX = 0;
	sort(vec2.begin(), vec2.end());
	for (int i = 0; i < vec1.size(); i++)
	{
		if (vec1[i] == vec2[i] && vec1[i] > MAX) //更改后的条件
			vec3.push_back(vec1[i]);
		if (vec1[i] > MAX) //MAX用来记录左边的最大值
			MAX = vec1[i];
	}
	sort(vec3.begin(), vec3.end());
	cout << vec3.size() << endl;
	for (int i = 0; i < vec3.size(); i++)
	{
		if (i != 0) cout << ' ';
		cout << vec3[i];
	}
	cout << endl;
	return 0;
}

注意最后要cout << endl;来输出换行,可能表示当不存在主元时,要输出0然后换两行

发布了101 篇原创文章 · 获赞 1 · 访问量 1956

猜你喜欢

转载自blog.csdn.net/weixin_43318827/article/details/105314928