编程之美2.3 寻找发帖水王

这道题目由于不容易写测试用例,所以,可以把题目转换为:在一个数组中,有一个数字出现的次数超过了数组大小的一半,这和题目原意是一样的。

这道题目的思想是我们同时去掉数组中两个不一样的数字,那么,数组中原来存在的规律是不变的(仅针对这个题目)。

好吧,还是先给出函数声明:

/*2.3 寻找发帖水王*/
bool DutVerify(int*, int, int);
int DutFindNumMoreThanHalf(int*, int);

可以看到,函数声明中多了一个:DutVerify,这个函数的作用是验证,即我们一定可以在一个不为空的数组中找到一个数字,但是,我们不能说明这个数字出现的次数就超过了数组长度的一半,所以,考虑到算法的健壮性,我们还是需要最后验证一下。

由于注释都已经写在了代码里,这里不多做解释,贴代码吧:

/*验证有效函数*/
bool DutVerify(int* A, int size, int result)
{
	/*出现的次数*/
	int count = 0;

	for (int i = 0; i < size; ++i)
	{
		if (A[i] == result)
			++count;
	}
	/*验证出现的次数是否大于数组长度的一半*/
	if (count > (size / 2))
		return true;
	else
		return false;
}

/*这个题目转换为数组中存在某一个数,这个数出现的次数大于数组中元素个数的一半*/
/*全局变量标识输入参数是否有效*/
bool _DutFindNumMoreThanHalf = false;
int DutFindNumMoreThanHalf(int* A, int size)
{
	if (!A || size <= 0)
	{
		_DutFindNumMoreThanHalf = true;

		return -1;
	}

	int result;
	int count = 0;

	/*
	 *这里的思想是同时去掉两个不一样的数字,那么数组的“原型”不会改变,
	 *即大于一半的那个数字在当前的数组中还是大于当前个数的一半
	 */
	for (int i = 0; i < size; ++i)
	{
		if (count == 0)
		{
			result = A[i];
			++count;
		}
		else
		{
			if (result == A[i])
				++count;
			else
				--count;
		}
	}
	/*当得到这个数字之后,我们需要验证这个数字是否出现的次数大于总个数的一半*/
	bool res = DutVerify(A, size, result);

	if (res == true)
		return result;
	else
	{
		_DutFindNumMoreThanHalf = true;

		return -1;
	}
}
时间: 2024-10-25 03:13:10

编程之美2.3 寻找发帖水王的相关文章

编程之美3:寻找数组中的最大值和最小值以及最大值和次大值

很开心,这是今天的第三篇文章啦!下午健身也感觉非常过瘾,托付宿舍妹子从日本代购的护肤品也到了.耳边漂浮着Hebe田馥甄的<魔鬼中的天使>文艺的声线,一切都好棒,O(∩_∩)O哈哈~.爱生活,爱音乐,爱运动,额,当然还有要爱学习啦!加油(^ω^) 额,扯远了.第三篇是关于寻找数组中的最大值和最小值.第一次看到这个题目的时候,楼主稍微鄙视了一下,因为觉得这个题目有什么好做的.但是楼主还是看了看<编程之美>上的写的,发现还是有必要记录一下,不一样的思考方式.很赞!大家和楼主一起哦,Are

编程之美2.10 寻找数组中的最大值和最小值

这个问题其实很容易解决,就是循环遍历一遍数组,然后找到数组中存在的最大值和最小值就可以了,书中主要讨论的问题是比较次数较小的方法,不过,书中已经证明了,无论用什么方法最少的比较次数也就是循环遍历一遍的比较,结果是O(1.5N)的,所以,很容易的可以解决这个问题. 第一种方法: 函数声明: void DutFindMaxAndMinInArray_1(int*, int, int&, int&); 源代码如下: /*基本的解法寻找最大值和最小值*/ bool _DutFindMaxAndMi

编程之美2.3——寻找水军(抵消法)

1.在数组中寻找出现次数超过一半的一个元素. 2.在数组中寻找出现次数超过1/4的三个元素. [思路] 1)常规做法:先将数组排序,时间O(nlogn):再遍历一次,统计每个元素出现的次数,得到题目要求. 2)时间O(n)的做法:抵消法.对于第一题,每次抵消两个不同的数,剩下的数组主元素出现次数还是超过一半.即缩小题目规模的思想. 对于第二题,则每次抵消4个数,转化为规模较小的问题. 抵消两个数的代码很简单: int findOverHalf(int *ID, int N){ int ntime

编程之美2.5 寻找最大的K个数

在一个数组中寻找最大的K个数,我们首先说一种非常简单的方法,利用快速排序中的分割算法,即我们经常看见的partition.这个函数会返回一个 int 类型的值,这个值代表的是前一半数字和后一半数字的分割点,前一半数字都小于等于后一半数字(递增排序),所以,我们只要找到相对应的分割点,即可以找到最大的K个数,或者最小的K个数,这就是利用线性方法可以完成任务的方法. 首先,给出函数声明: int DutPartition(int*, int, int); void DutFindMaxKInArra

编程之美2.3: 寻找发帖水王

题目:传说,Tango有一大"水王",他不但喜欢发帖,还会回复其他ID发的帖子,发帖数目超过帖子总数的一半,如果你有一个当前论坛上所有帖子的列表,其中帖子作者的ID也在表中,你能快速找到这个传说中的Tango水王吗? 解题思路:由于水王的发帖数目超过一半,当每次删除两个不同ID的帖子时,水王占得帖子数目仍然大于剩下帖子的一半,重复整个过程,将ID列表中的ID总数降低,转化为更小的问题,从而得到最后水王的ID. #include <iostream> #include <

主元素 寻找发帖水王

寻找发帖“水王” 题目是这样描述的:“水王”发帖的数目超过了所有帖子的一半,有各个帖子的作者ID,求这个水王的ID 编程之美给出了两种巧妙的解法 解法一:ID排序,那么ID列表中的N/2项即为要找的ID(还要排序,时间复杂度为O(NlogN)) 解法二:通过查找,每次从列表中除去两个不一样的ID,最后就可以得出这个ID,时间复杂度O(N).写法上也有技巧,不必非要找到一个不一样的在继续下去,如果下一个一样,那么用一个变量记录这个次数,把次数+1,遇见不一样的-1.例如1,1,2,3,4 初始va

编程之美2.14 求数组的子数组之和的最大值

问题描述: 一个有N个整数元素的一维数组(A[0], A[1], A[2],...,A[n-1]),这个数组当然有很多子数组,那么子数组之和的最大值是什么呢? 解法: 1. 暴力解法-------O(N^3) 2. 改进版暴力解法-------O(N^2) *3. 分治算法-------O(NlogN)(暂时未去实现) 4. 数组间关系法-------O(N) 具体思路和代码: 1.暴力解法 思路:Sum[i,...,j]为数组第i个元素到第j个元素的和,遍历所有可能的Sum[i,...,j].

寻找发帖水王02

题目:随着论坛的发展,管理员发现水王没有了,但是统计结果表明,有3个发帖很多的ID.据统计他们的发帖数目都超过了帖子总数目的1/4,你能从发帖列表中快速找出他们吗? 设计思路: 水王01只需要一个结果,而现在需要3个结果,上题用到的nTimes,也应改为3个计数器.现在需要3个变量来记录当前遍历过的3个不同的ID,而nTimes的3个元素分别对应当前遍历过的3个ID出现的个数.如果遍历中有某个ID不同于这3个当前ID,就判断当前3个ID是否有某个的nTimes为0,如果有,那这个新遍历的ID就取

编程之美2.17 数组循环移位

问题描述: 设计一个算法,把一个含有N元素的数组循环左移或者右移K位. 解决方法: 1. 暴力解法------O(KN) 2. 颠倒位置------O(N) 具体思路和代码: 1. 暴力解法------O(KN) 思路:循环K次,每次移动一位 代码: 1 //右移 2 void s1(int A[], int n, int k) 3 { 4 k = k % n; 5 for(int i = 0; i < k; i++) 6 { 7 int t = A[n-1]; 8 for(int j = n-