(贪心)Make a Permutation!

10 篇文章 0 订阅
4 篇文章 0 订阅

题意:

给你一个长度为n的序列,元素大小为1-n。让你修改某些元素值,使得整个序列出现的元素不重复(修改值范围为1-N);求在修改操作数最少的前提下,使得修改后的序列字典序最小,

思路:

贪心
由题意知道修改操作最少为1~n没出现过的数的个数。要使得字典序最小,那么就要从头部开始插入,平且插入可选的最小值。

当某个位置的数num出现次数大于二,那么可进行插入判断。两种情况:

  1. t<num,可直接插入

  2. t>num。。如果后面直接插入,字典序不是最小的,那么当前数为num,那么往后出现num,不管num与t的大小如何,都必须插入。以上转自感谢博主

题目链接D. Make a Permutation!

#include<bits/stdc++.h>

using namespace std;

int main()
{
    int n,a[200010];
    int num = 1,flag = 0;//num就是要找没有出现过的数字,flag是最后替换掉的数字
    int exi[200010] = {0},vis[200010] = {0};//vis数组用来储存每个数字出现的次数
    scanf("%d",&n);//exi数组用来处理当一个数字多次出现的时候是否进行替换
    for(int i = 1; i <= n; i++)
    {
        scanf("%d",&a[i]);
        vis[a[i]]++;//统计每个数字出现的次数
    }
    for(int i = 1; i <= n; i++)
    {
        if(vis[a[i]] > 1)//出现过两次或以上,说明这个位置可能会发生替换
        {
            while(vis[num])//这里用来从小到大找没有出现过的数字
            num++;
            if(num >= a[i] && exi[a[i]] == 0)//这里就是说我们已经为数组预留了一个
            {	//这个数字了,所以后面这个数字再次出现的时候无论大小都要替换
                exi[a[i]]++;
            }
            else//小于就是可以直接替换的
            {
                flag++;
                vis[a[i]]--;//替换掉之后被替换的数字出现次数减一
                vis[num]++;//用来替换的数字次数加一
                a[i] = num;//这个语句一定要放在“vis[a[i]]--;”这个语句后面
            }
        }
    }
    printf("%d\n",flag);
    for(int i = 1; i < n; i++)
    {
        printf("%d ",a[i]);
    }
    printf("%d\n",a[n]);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值