蓝桥杯第十届真题 - 修改数组(两种思路)

题目链接

AC:普通数组

vis 数组统计每个数被访问的次数,如果一个数被访问了 k 次,则该数的后 k 个数一定都存在,则直接跳转到 k 后面继续判断。

还有需要注意的是:在输入输出数据很大的时候,建议使用 scanf 和 printf 取代 cin 和 cout,不然可能会超时。这道题就是。

#include <iostream>
using namespace std;
const int MaxNum = 1000005;
int vis[MaxNum];

int main() {
    int n;
    cin >> n;
    while (n--) {
        int num;
        scanf("%d", &num);
        while (vis[num]) {
            int tmp = num;
            num += vis[num];
            ++vis[tmp];
        }
        vis[num] = 1;
        printf("%d ", num);
    }
    return 0;
}

map:超时

对于同样的思路,如果使用 map 则会超时,因为使用 [] 或 find 成员函数访问时都是要遍历查找的,没有普通数组那么快。

#include <iostream>
#include <map>
using namespace std;

int main() {
    int n;
    cin >> n;
    map<int, int> nums;
    while (n--) {
        int num;
        cin >> num;
        map<int, int>::iterator iter = nums.find(num);
        while (iter != nums.end()) {
            int tmp = num;
            num += iter->second;
            ++nums[tmp];
            iter = nums.find(num);
        }
        nums[num] = 1;
        printf("%d ", num);
    }
    return 0;
}

AC:并查集

思路:对于所有的数,起初他们的根节点都指向自己,表示没出现过。当遇到一个数时,找到他的根节点,由于根节点始终是未出现过的,所以输出根节点,接着把根节点再指向一个新的根节点(比旧的根节点大 1),这样就能始终保持根节点是未出现过的了。

在查找根节点的同时使用路径压缩,可以更快的查找到根节点。

6
1 2 3 4 1 3
遇到 1,1 的根节点是 1,输出 1,指向新的根节点 2,也就是 par[1] = 1 + 1;
遇到 2,2 的根节点是 2,输出 2,指向新的根节点 3
遇到 3,3 的根节点是 3,输出 3,指向新的根节点 4
遇到 4,4 的根节点是 4,输出 4,指向新的根节点 5
遇到 1,1 的根节点是 5,输出 5,指向新的根节点 6
遇到 3,3 的根节点是 6,输出 6,指向新的根节点 7
#include <iostream>
using namespace std;
const int MaxNum = 1000005;
int par[MaxNum];
void init() {
    for (int i = 0; i < MaxNum; ++i) par[i] = i;
}

int find(int x) {
    if (par[x] == x)
        return x;
    else
        return par[x] = find(par[x]);
}
int main() {
    int n;
    cin >> n;

    init();
    while (n--) {
        int num;
        scanf("%d", &num);
        int root = find(num);
        printf("%d ", root);
        par[root] = root + 1;
    }
    return 0;
}

比较

普通数组:228ms
并查集:39ms

参考资料

  1. [蓝桥杯][2019 年第十届真题]修改数组-题解(C++代码)-Dotcpp 编程社区
  2. [蓝桥杯][2019 年第十届真题]修改数组-题解(C++代码)(链表式并查集 + 这是什么神仙算法)-Dotcpp 编程社区
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值