Programe_Of_Beauty:2.3 寻找发帖“水王”及扩展问题

问题:其实问题可以简单的说:有一个数组,数组中的某个元素出现的次数超过N/2。问有没有很好的方法快速找到这个元素。

解析:如:char ID[5] = { ‘a’,‘b’,‘a’,‘c’,‘a’};a的出现次数为3。一个很高效的方法就是:当两个元素不相同时就把这两个元素都删除,这样最后剩下的就是要找的元素,当然不一定是真的删除。

#ifndef _2_3_TANGO_H_
#define _2_3_TANGO_H_
//2.3寻找发帖水王 p129
#include <iostream>
//本题目的含义是,在一个序列中寻找出现次数最多的id,如a,a,b,c,a,b,a,a 当然a出现次数最多
//如果遍历的话要n^2的复杂度,如果排序的话也要n*logn的时间,如何在n的时间内找到呢?
using namespace std;

void TangoFind(char* arrID, int size)
{
	char candidate;
	int nTimes = 0;//元素出现次数
	for (int i = 0; i < size; ++i)//如果有两个元素不同,则删除这两个元素,当然不是真的删除
	{
		if (0 == nTimes)//记录某个元素和其它元素不同的次数
		{
			candidate = arrID[i];//如果nTimes为0,则表明 在这之前的元素 如a,b,b,c有偶数个不同对 出现,当然都删除
		} 
		else
		{
			if (candidate == arrID[i])//如果这个元素又出现 则加1
			{
				nTimes++;
			} 
			else//如果这个元素没有出现,就是当前的与它不同 就--
			{
				nTimes--;
			}
		}
	}
	cout<<"candidate="<<candidate<<endl;
}
#endif//_2_3_TANGO_H_

扩展问题:着Tango的发展,管理员发现,“超级水王”没有了。统计结果表明,有3个发帖很多的ID,他们的发帖数目都超  过了帖子总数目N的1/4。你能从发帖ID列表中快速找出他们的ID吗?

关键想法是:先记录3个不的元素,然后再计算下一个元素是否出现在已经记录的3个元素中,如果有则相应的加1,如果没有则3个元素都减1.

    int a[] = {1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,4,5,6,7,9};

    int aTimes=0;
    int bTimes=0;
    int cTimes=0;
    int aCur=0;
    int bCur=0;
    int cCur=0;
    //int cur=0;
    for (int i = 0; i < 20; i++)
    {
		if (aTimes ==0)
		{
			aCur = a[i];
			aTimes = 1;
		}
		else
		{
			if (aCur == a[i])
			{
				aTimes++;
			} 
			else
			{
				if (bTimes == 0)
				{
					bCur = a[i];
					bTimes = 1;
				} 
				else
				{
					if (bCur == a[i])
					{
						bTimes++;
					} 
					else
					{
						if (cTimes == 0)
						{
							cCur = a[i];
							cTimes = 1;
						} 
						else
						{
							if (cCur == a[i])
							{
								cTimes++;
							} 
							else
							{
								aTimes--;
								bTimes--;
								cTimes--;
							}
						}
					}
				}
			}
		}
    }
	cout<<aCur<<"  "<<bCur<<"  "<<cCur<<endl;
}

结果为:1 2 3。当然我们发现,有3个元素都超过了总数的1/4,那么这3个元素的总和超过了3/4,我们可以用一个桶来操作,桶的大小为(1/4)*N +3。或者用map关联容器也可以。

转载于:https://www.cnblogs.com/cluster/archive/2011/06/06/2073674.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值