主元素问题的多种解法

Part -1:版权声明:

本文大部分代码来自这篇博文

Part 0:啥是主元素问题

给一个有n个元素的数列,保证有一个数a出现的次数超过50%,求这个数

Part 1:桶计数做法

桶计数做法是出现一个数,就把这个数出现次数+1,很好懂:

#include <bits/stdc++.h> using namespace std; int ans[10001],n,t; int main(){ cin>>n; for(int i=0;i<n;i++){ cin>>t; ans[t]++; } for(int i=0;i<10001;i++) if(ans[i]>n/2){ cout<<i; break; } }

很好懂,时间复杂度O(N+M)
但是,一旦利用桶的思想,就不可避免的遇到一个问题:空间
比如我给你的数是这样的:

1 12398517923876091 1000 1000000 10000000000 9999999 2345234618 1239 102358 12398517923876091 12398517923876091 12398517923876091 12398517923876091 12398517923876091 12398517923876091

请问你要开多大的空间?12398517923876091个数组
好,有的同学说可以离散化,我再给你一组数据:

1 2 3 4 5 6 ... LONG_MAX 1 1 1 ...(LONG_MAX/2个1)

从1到LONG_MAX全部给你,你怎么做?你继续离散化啊?你离散啊你离散啊你离散啊~
(别问我为什么数据这么毒瘤,我自己出数据就是这么毒瘤)

Part 2: 排序做法

显然,若一个数列存在主元素,那么这个主元素在排序后一定位于n2的位置
那么我们又有想法了:

#include <bits/stdc++.h> using namespace std; int n,a[10001]; int main() { cin>>n; for(int i=0;i<n;i++) cin>>a[i]; sort(a,a+n);//C++ STL自带排序函数 cout<<a[n/2+1-1];//减1是因为这里数组从a[0]开始用 return 0; }

看起来不错!O(NlogN)的复杂度可还行?
于是,一旦有NlogN,就一定有人想出N。有吗?还真的有——

Part 3:终极做法

这个数列有个特性:由于主元素的出现的次数超过50%,那么在不断的消掉两个不同的元素之后,最后一定剩下主元素
有的同学会问了:如果数列长度为偶数呢?
我说这位同学,请 你 审 题

给一个有n个元素的数列,保证有一个数a出现的次数超过50%,求这个数

再读一次:

保证有一个数a出现的次数超过50%

还不懂?再读一次:

超过50%

再不懂?滚!
输入时判断与上一次保存的输入是否相同,如不同则删除两数,这里用栈来实现。

#include<stdio.h> int n,q[10001],top=0,a; int main() { scanf("%d",&n); while(n--)scanf("%d",&a),q[top++]=a,top=(top>1&&(q[top-1]!=q[top-2]))?top-2:top; printf("%d",q[top-1]); }

__EOF__

本文作者SDLTF
本文链接https://www.cnblogs.com/sdltf/p/12389775.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   SD!LTF  阅读(848)  评论(6编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示