D2170(女朋友算法;桶的思想开多少个桶?;初识时间复杂度)

Description

给定n个正整数a[1],a[2],a[3],…,a[n].有m次操作

1 i t:将a[i]修改为t

2 k:输出k-众数

k-众数是指在这n个正整数中,出现次数最多且出现的正整数小于等于k的数(如果有多个,输出最小的)。

Input

第一行包含用空格隔开的两个正整数n m

第二行,包含n个用空格隔开的正整数a[1],a[2],a[3],…,a[n]

接下来m行,每行包含两个(opt k)或三个正整数(opt i t)

Output

对于每个操作2,输出k-众数,若不存在,则输出-1

Sample Input

10 10
1 2 3 4 5 6 7 8 9 10
2 1
2 10
1 1 2
1 3 2
1 4 2
1 5 2
1 7 2
1 8 2
2 1
2 10

Sample Output

1
1
-1
2

HINT

对于100%的数据,保证1≤n,m,a[i],t≤102,k≤109

问题

  1. 知道用桶的思考和寻找众数的方法,也搭好了基本框架,代码如下,但交题时超时了(程序运行超过1s),为什么呢?
#include<bits/stdc++.h>
using namespace std;
 
int f2(int* p,int l,int k,int *y)
{
    int s[150]={0};int x,i;
    for(i=0;i<l;i++)
    {
        x = *(p+i);
        s[x]++;
    }
    int maxcs = -1;
    for(i=0;i<=k;i++)
    {
        if(s[i]>maxcs)
        {maxcs = s[i];}
    }
    for(i=0;i<=k;i++)
    {
        if(s[i]==maxcs&&i<=k)
        {*y = i;return 0;}
    }
    *y = -1;return 0;
 
}
 
int f1(int* p,int i,int t)
{
    *(p+i) = t;
    return 0;
}
 
int main()
{
    int n,m;
    cin >> n >> m;
    int s[n];
    int j;
    for(j=0;j<n;j++)
    {
        cin >> s[j];
    }
    int x,i,t,k,y;
    while(m--)
    {
        cin >> x;
        if(x==1)
        {cin >> i >> t;f1(s,i,t);}
        else if(x==2)
        {cin >> k;f2(s,n,k,&y);cout << y << endl;}
    }
}

---->根据题目范围:k<=109 而一秒最多跑107而函数f2有2次遍历1到k,所以一定会超时,因此要减少遍历的范围。
2. 如何减少遍历的范围?
----->for循环从1到110而不是1到k
3. 为什么是1到110呢?
------>因为由题目知 t<=102故桶的下标最大不超过100,最多只有100个桶(如果k小于100,就只有k个桶)

总结

  1. 注意数据取值范围,程序1s最多跑107如果数据过大,就要减少算法时间复杂度
  2. 桶的思想:开多少个桶?------>取决于一组数据的最大值,如果5个数{3,9,12,34,22}就开34个桶;但有时会加工这些数,使其在一个很小的范围,如 一组数{103,109 …},对数组再次赋值,使其在100以内,这时就只要开100个桶
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值