反推排序----报数问题
题目:
有n个人,编号从1到n,可以进行任意的排序,排序好后,从头开始报数,第一个人默认报数0,此后每个人报数前面比自己编号小的数量,比如排序为3,5,2,1,4,有报数为0,1,0,0,3,那么现在根据给定的报数来反推排序
思路:
看到这题目不难懂,题目给提示了,用反堆排序。那么先从简单的入手,全升序和全倒叙的情况,就不过多叙述了。在做到全升序时,其实有个很明显的特征就是:本身位置+1==>大小
也就是说,报数+1==>大小 因此,开始去讨论了,对于取到6人,分别为0,1,1,1,1,4这种情况下,该怎么去做呢。
很简单哈,简单的数学问题,一定要去写示例,那么开始:
从简单的5个人开始-------0,1,0,2,4或者0,1,0,3,4再或者0,1,1,1,4
那么也很快,答案分别是:2,4,1,3,5-------1,3,2,4,5-----1,4,3,2,5
所有的数都是往左侧开始判断大小从而报数的,并且计算机目前是不可能像我们人一样,跳着这么选择判断获取值的,因为这样操作会增加性能压力,增加不必要的操作。
那么从右往左开始计算操作,很明显的就得到了,依次增加1,也就是count+1==>count++
但是呢,还不够,比如6人时,0,1,1,1,1,4这样的情况呢,这时候就要去增加一个判断,判断这个大小,是否被获取到,这时候肯定是要去新建一个数组,让数组大小存储我们的值,或者说让他默认为0==>false
这时候基本思路就通了。我在循环里面加了一个条件,是对0,1,2,3,4,5这种index=num[index]+1的情况,做的时候迷糊,就留下来了,而且为了保证后续的意外,我让判断大小是否获取的数组从0开始循环。
要是有什么更好的思路,或者能够提高性能优化的,滴滴我。
代码
#include <iostream>
#include <vector>
int main() {
int n;
std::cout << "请输入大小: ";
std::cin >> n;
std::vector<int> num(n);
int a;
std::cout << "请输入报数: ";
std::vector<bool> BB(n+1);//记录哪些数被取到了
for (int i = 0; i < n; i++) {
std::cin >> a;
num[i] = a;
BB[i] = false;
}
std::vector<int> result(n);//输出数组
result[n - 1] = num[n - 1] + 1;
BB[result[n - 1]] = true;
int count = 1;
for (int i = n - 1; i > 0; i--)
{
if (num[i - 1] == num[i] - 1)
{
result[i - 1] = num[i - 1] + 1;
BB[result[i - 1]] = true;
count++;
}
else
{
result[i - 1] = BB[num[i - 1] + count] ? num[i - 1] + count + 1 : num[i - 1] + count;
BB[result[i - 1]] = true;
count++;
}
}
std::cout << "推导出的排列为: ";
for (int i = 0; i < n; ++i) {
std::cout << result[i] << " ";
}
std::cout << std::endl;
return 0;
}