原题链接: http://acm.hdu.edu.cn/showproblem.php?pid=1029
测试样例
Sample Input
5
1 3 2 3 3
11
1 1 1 1 1 5 5 5 5 5 5
7
1 1 1 1 1 1 1
Sample Output
3
5
1
题意: 给你一个奇数长度大小的整数序列,你需要找出其中一个元素,它至少出现了
次。
解题思路: 这里我们有两种方法去解决。先说通俗的解法,即是用map容器来解决,我们对每次输入进行记录,并判断它符合要求。对符合要求的值进行存储, 最后输出即可。很好理解。那么还有一种方法就是动态规划。这种方法十分巧妙,我们首先要确定一个事实,就是这个整数序列只能出现一个符合要求的元素。因为它至少出现次。所以我们则可以设这个元素就为
,那么它出现的次数就为
。再想一想,在前
个数中,如果没有一个数出现次数超过
,那么这个数必定在剩下的
个数中出现。所以,我们可以判断当输入数值不等于我们当时所假设这个元素时,那么这个出现次数就减,若为,则加。这样的目的是为了判断我们在剔除过程中到底有没有一个元素可以出现超过一半。所以我们在
时我们需要更换我们的假定值,因为它已经不可能了。OK,具体看代码。
STL AC代码
/*
*
*
*/
//POJ不支持
//i为循环变量,a为初始值,n为界限值,递增
//i为循环变量, a为初始值,n为界限值,递减。
using namespace std;
const int inf = 0x3f3f3f3f;//无穷大
const int maxn = 1e5;//最大值。
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
//*******************************分割线,以上为自定义代码模板***************************************//
int n,temp;
int main(){
//freopen("in.txt", "r", stdin);//提交的时候要注释掉
IOS;
while(cin>>n){
int result;
map<int,int> p;
rep(i,0,n-1){
cin>>temp;
if(++p[temp]>=(n+1)/2){
result=temp;
}
}
cout<<result<<endl;
}
return 0;
}
动态规划AC代码
/*
*
*
*/
//POJ不支持
//i为循环变量,a为初始值,n为界限值,递增
//i为循环变量, a为初始值,n为界限值,递减。
using namespace std;
const int inf = 0x3f3f3f3f;//无穷大
const int maxn = 1e5;//最大值。
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> pll;
typedef pair<int, int> pii;
//*******************************分割线,以上为自定义代码模板***************************************//
int n,temp,result,cnt;
int main(){
//freopen("in.txt", "r", stdin);//提交的时候要注释掉
IOS;
while(cin>>n){
cnt=0;
rep(i,1,n){
cin>>temp;
if(cnt==0){
result=temp;
cnt++;
}
else{
if(temp==result){
cnt++;
}
else{
cnt--;
}
}
}
cout<<result<<endl;
}
return 0;
}