有趣的问题系列-主元素问题
什么是主元素问题?
给定一个有
怎么做?
朴素桶计数
我们第一想到的,至少我第一想到的就是桶计数。出现一个数,把它扔进桶中。桶计数是很基本的概念,如果你这都不懂,赶紧百度去!
代码实现也很简单,纯手敲吧,有锅不修。
#include <iostream>
#include <cstdio>
int bucket[10086];
int main() {
int n;
std :: cin >> n;
for(int i = 1; i <= n; i++) {
int x;
std :: cin >> x;
bucket[x]++;
}
for(int i = 1; i <= 10086; i++)
if(bucket[i] > n / 2) {
cout << i << std :: endl;
break;
}
return 0;
}
但是桶计数的局限性非常大,非常容易爆空间,int的范围就可以让这玩意儿直接gg。
如果你想到了离散化,说明你还是很聪明的,蟹蟹为你点赞。但是离散化并不是最好的方法,照样有很多东西会卡离散化。我们直接pass掉桶计数吧。
好吧我知道有些人又开始叫map了……稍安勿躁,我有更好的方案。
排序
这叫做更好的方案????蟹蟹你真是绝了。
先别急着爆踩我,首先一个数列如果存在主元素,则排序后第
我们就有了新方法:
#include <iostream>
#include <cstdio>
const int maxn = 10005;
int a[maxn];
int main() {
int n;
for(int i = 1; i <= n; i++)
std :: cin >> a[i];
sort(a + 1, a + n + 1);
std :: cout << a[n / 2 + 1];
return 0;
}
很明显此算法的复杂度是
还真有。以前还是个初学者的时候看到主元素问题思路就停止在这里了,前天有机会重新见到了这道题,我又有了新的想法。
互相抵消法
我们把序列中所有不相同的两个数互相抵消,剩下的就是主元素。因为主元素在数列中出现的数量严格大于
这里可以用很多种实现方式,我选择用stack
食用= =
#include <iostream>
#include <cstdio>
const int maxn = 10000005;
int s[maxn];
int top;
int main() {
int n;
scanf("%d",&n);
while(n--) {
int x;
scanf("%d",&x);
s[top++] = x;
if(top == 1) continue;
if(s[top - 1] != s[top - 2]) top -= 2;
}
printf("%d\n",s[top - 1]);
return 0;
}
后记
这个问题真的很有趣,也验证了我思维的成长过程。两年前我只能想到
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】