反推排序----报数问题

反推排序----报数问题

题目:

有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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值