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
问题
- 知道用桶的思考和寻找众数的方法,也搭好了基本框架,代码如下,但交题时超时了(程序运行超过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个桶)
总结
- 注意数据取值范围,程序1s最多跑107如果数据过大,就要减少算法时间复杂度
- 桶的思想:开多少个桶?------>取决于一组数据的最大值,如果5个数{3,9,12,34,22}就开34个桶;但有时会加工这些数,使其在一个很小的范围,如 一组数{103,109 …},对数组再次赋值,使其在100以内,这时就只要开100个桶