`
dogasshole
  • 浏览: 840285 次
文章分类
社区版块
存档分类
最新评论

找出数组中出现次数超过长度一半的数字

 
阅读更多

题目:数组中有一个数字出现的次数超过了数组长度的一半,找出这个数字。

分析:这是一道广为流传的面试题,包括百度、微软和Google在内的多家公司都曾经采用过这个题目。要几十分钟的时间里很好地解答这道题,除了较好的编程能力之外,还需要较快的反应和较强的逻辑思维能力。

看到这道题,我们马上就会想到,要是这个数组是排序的数组就好了。如果是排序的数组,那么我们只要遍历一次就可以统计出每个数字出现的次数,这样也就能找出符合要求的数字了。题目给出的数组没有说是排好序的,因此我们需要给它排序。排序的时间复杂度是O(nlogn),再加上遍历的时间复杂度O(n),因此总的复杂度是O(nlogn)

接下来我们试着看看能不能想出更快的算法。前面思路的时间主要是花在排序上。我们可以创建一个哈希表来消除排序的时间。哈希表的键值(Key)为数组中的数字,值(Value)为该数字对应的次数。有了这个辅助的哈希表之后,我们只需要遍历数组中的每个数字,找到它在哈希表中对应的位置并增加它出现的次数。这种哈希表的方法在数组的所有数字都在一个比较窄的范围内的时候很有效。本博客系列的第13就是一个应用哈希表的例子。不过本题并没有限制数组里数字的范围,我们要么需要创建一个很大的哈希表,要么需要设计一个很复杂的方法来计算哈希值。因此总体说来这个方法还不是很好。

前面两种思路都没有考虑到题目中数组的特性:数组中有个数字出现的次数超过了数组长度的一半。也就是说,有个数字出现的次数比其他所有数字出现次数的和还要多。因此我们可以考虑在遍历数组的时候保存两个值:一个是数组中的一个数字,一个是次数。当我们遍历到下一个数字的时候,如果下一个数字和我们之前保存的数字相同,则次数加1。如果下一个数字和我们之前保存的数字不同,则次数减1。如果次数为零,我们需要保存下一个数字,并把次数设为1。由于我们要找的数字出现的次数比其他所有数字出现的次数之和还要多,那么要找的数字肯定是最后一次把次数设为1时对应的数字。

基于这个思路,我们不难写出如下代码:

bool g_bInputInvalid = false;

<wbr></wbr>

//////////////////////////////////////////////////////////////////////////

// Input: an array with "length" numbers.<wbr>A number in the array</wbr>

// appear more than "length / 2 + 1" times.

// Output: If the input is valid, return the number appearing more than

// "length / 2 + 1" times. Otherwise, return 0 and set flag g_bInputInvalid

// to be true.

//////////////////////////////////////////////////////////////////////////

int MoreThanHalfNum(int* numbers, unsigned int length)

{

<wbr><wbr><wbr> if(numbers == NULL &amp;&amp; length == 0)</wbr></wbr></wbr>

<wbr><wbr><wbr> {</wbr></wbr></wbr>

<wbr><wbr><wbr><wbr><wbr><wbr><wbr> g_bInputInvalid = true;</wbr></wbr></wbr></wbr></wbr></wbr></wbr>

<wbr><wbr><wbr><wbr><wbr><wbr><wbr> return 0;</wbr></wbr></wbr></wbr></wbr></wbr></wbr>

<wbr><wbr><wbr> }</wbr></wbr></wbr>

<wbr></wbr>

<wbr><wbr><wbr> g_bInputInvalid = false;</wbr></wbr></wbr>

<wbr></wbr>

<wbr><wbr><wbr> int result = numbers[0];</wbr></wbr></wbr>

<wbr><wbr><wbr> int times = 1;</wbr></wbr></wbr>

<wbr><wbr><wbr> for(int i = 1; i &lt; length; ++i)</wbr></wbr></wbr>

<wbr><wbr><wbr> {</wbr></wbr></wbr>

<wbr><wbr><wbr><wbr><wbr><wbr><wbr> if(times == 0)</wbr></wbr></wbr></wbr></wbr></wbr></wbr>

<wbr><wbr><wbr><wbr><wbr><wbr><wbr> {</wbr></wbr></wbr></wbr></wbr></wbr></wbr>

<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr> result = numbers[i];</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>

<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr> times = 1;</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>

<wbr><wbr><wbr><wbr><wbr><wbr><wbr> }</wbr></wbr></wbr></wbr></wbr></wbr></wbr>

<wbr><wbr><wbr><wbr><wbr><wbr><wbr> else if(numbers[i] == result)</wbr></wbr></wbr></wbr></wbr></wbr></wbr>

<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr> times++;</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>

<wbr><wbr><wbr><wbr><wbr><wbr><wbr> else</wbr></wbr></wbr></wbr></wbr></wbr></wbr>

<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr> times--;</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>

<wbr><wbr><wbr> }</wbr></wbr></wbr>

<wbr></wbr>

<wbr><wbr><wbr> // verify whether the input is valid</wbr></wbr></wbr>

<wbr><wbr><wbr> times = 0;</wbr></wbr></wbr>

<wbr><wbr><wbr> for(int i = 0; i &lt; length; ++i)</wbr></wbr></wbr>

<wbr><wbr><wbr> {</wbr></wbr></wbr>

<wbr><wbr><wbr><wbr><wbr><wbr><wbr> if(numbers[i] == result)</wbr></wbr></wbr></wbr></wbr></wbr></wbr>

<wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr> times++;</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>

<wbr><wbr><wbr> }</wbr></wbr></wbr>

<wbr></wbr>

<wbr><wbr><wbr> if(times * 2 &lt;= length)</wbr></wbr></wbr>

<wbr><wbr><wbr> {</wbr></wbr></wbr>

<wbr><wbr><wbr><wbr><wbr><wbr><wbr> g_bInputInvalid = true;</wbr></wbr></wbr></wbr></wbr></wbr></wbr>

<wbr><wbr><wbr><wbr><wbr><wbr><wbr> result = 0;</wbr></wbr></wbr></wbr></wbr></wbr></wbr>

<wbr><wbr><wbr> }</wbr></wbr></wbr>

<wbr></wbr>

<wbr><wbr><wbr> return result;</wbr></wbr></wbr>

}

<wbr></wbr>

<wbr><wbr><wbr><wbr><wbr><wbr></wbr></wbr></wbr></wbr></wbr></wbr> 在上述代码中,有两点值得讨论:

(1)<wbr><wbr><wbr><wbr><wbr><span style="font-size:16px">我们需要考虑当输入的数组或者长度无效时,如何告诉函数的调用者输入无效。关于处理无效输入的几种常用方法,在</span><a href="http://zhedahht.blog.163.com/blog/static/25411174200731139971/"><span style="font-size:16px"><span style="color:#990000">本博客系列的第<span style="font-family:Calibri">17</span>题</span></span></a><span style="font-size:16px">中有详细的讨论;</span></wbr></wbr></wbr></wbr></wbr>

(2)<wbr><wbr><wbr><wbr><wbr><span style="font-size:16px">本算法的前提是输入的数组中的确包含一个出现次数超过数组长度一半的数字。如果数组中并不包含这么一个数字,那么输入也是无效的。因此在函数结束前我还加了一段代码来验证输入是不是有效的。</span></wbr></wbr></wbr></wbr></wbr>

<wbr></wbr>

博主何海涛对本博客文章享有版权。网络转载请注明出处http://zhedahht.blog.163.com/。整理出版物请和作者联系。对解题思路有任何建议,欢迎在评论中告知,或者加我微博http://weibo.com/zhedahht或者http://t.163.com/zhedahht与我讨论。谢谢。

分享到:
评论

相关推荐

    数组中出现次数超过一半的数字1

    数组中出现次数超过一半的数字数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。示例 1:输入: [1, 2, 3, 2, 2, 2, 5, 4, 2

    PHP实现找出数组中出现次数超过数组长度一半的数字算法示例

    主要介绍了PHP实现找出数组中出现次数超过数组长度一半的数字算法,涉及php数组的遍历、统计、判断等相关操作技巧,需要的朋友可以参考下

    php实现数组中出现次数超过一半的数字的统计方法

    数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。 两种方式: 1...

    剑指Offer(Python多种思路实现):数组中出现次数超过一半的数字

    题:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。 解题思路...

    Python 找出出现次数超过数组长度一半的元素实例

    主要介绍了Python 找出出现次数超过数组长度一半的元素实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

    leetcode跳跃-coding-note:编码注释

    数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。 3.最小的K个数...

    世界500强面试题.pdf

    1.5.3. 在字符串中找出连续最长的数字串 ....................................................109 1.5.4. 链表操作..............................................................................................

    java 经典习题.doc

    编程 找出1000以内的所有完数。 【程序10】 题目:一球从100米高度自由落下,每次落地后反跳回原高度的一半;再落下,求它在 第10次落地时,共经过多少米?第10次反弹多高? 【程序11】 题目:有1、2、3、4个...

    华为编程开发规范与案例

    1 逻辑类问题(A类)-指设计、编码中出现的计算正确性和一致性、程序逻辑控制等方面出现的问题,在系统中起关键作用,将导致软件死机、功能正常实现等严重问题; 接口类问题(B类)-指设计、编码中出现的函数和...

    最新JAVA编程题全集_50题及答案

    System.out.println("数据长度:"+len); left = 0; right = len - 1; while (left ) { //由于源数据不是顺序的,需先进行排序 int temp; for(int i=0;i;++i) { for(int j=0;j;++...

Global site tag (gtag.js) - Google Analytics