主元素问题探索算法的妙不可言

来源:互联网 发布:au cs6 mac 汉化 编辑:程序博客网 时间:2024/04/29 15:40

题目描述:

已知一个数组的大小,并且其中存在一个数,出现的频率大于50%,则称其为该数组的主元素。用一个算法找出这个数,要求其时间复杂度尽可能低。

ps:看过《啊哈,算法》的朋友或许知道这是作者当年的面试题目,据说还是一道考研题目。(未查证,只是听说而已)

题目分析

拿到这道题目,就题目描述来看,显然这道题目就是单纯的找一个数嘛。

Q: 额?就完了,这也叫分析题目?
A:hhhh,对呀,就是这样分析题目的呀。在我的潜意识里,在看题目的时候我一般不会直接就开始想怎么怎么去解答一个问题,而是弄清楚这道题目告诉了我们什么,需要我们解答什么。嗯,对,就是这样就行了。

额,好吧,我还是再来简单的说下题目的意思:
对于这道题目,讲述很短,那我们就需要从题意当中找出已知的信息以及一些我们需要踩的坑。这道题目给出了我们的数据总数为N,需要在其中找出一个出现次数大于N/2的数。
那么我们可以简单的罗列下:

  • 已知总数为N(大小未知)
  • 其中有一个数出现次数大于N/2
  • 只需要找到这个数
  • 没有告诉数的类型

(当然我们这道题目需要探究的不是数据类型方面或者编程实现,而是为了引入算法的“秒”给大家品尝)

题目解析

解法一:暴力法O(n*n)

最容易想到也是最容易实现的算法就是直接进行计数,总的来说复杂度大概为冒泡排序大小,,具体的代码实现请聪明的你自行实现(特别是对于不是很懂算法与数据结构的朋友,我强烈的建议你进行相应的实现)

解法二:排序、计数O(nlogn)

如果我先进行一个排序,我们使用最好效率的算法(啥?不知道最好的效率算法,朋友请移步:八大排序,数据结构中的八大排序算法、八大排序算法总结),看完了这三篇文章是不是对相应的排序算法有了认识呢?那你有没有找到最好效率的算法呢?

Q: 没有找到对吧?
A: 对
Q: 很好,其实对于算法来说,没有好坏之分,只有适当的时候运用到适当的场景的算法才称得上是对于此时的此场景的好算法,hhhhhhh,是不是有点晕了?不着急,简单的说就是算法之所以好坏其实是运用的效果来衡量的,每个算法都有自己的优缺点。

好,我们回到原来的问题上,对于这N个数的排序来说我们就运用最好效率的算法,具体的什么算法就等聪明的你去实现了(哈哈哈哈,是不是又有任务了,不用担心,不用着急,这种机会后边还多着呢),

对于排序后的N个数,我们再进行相应的统计计数,那么总的时间复杂度就为排序O(nlogn)+计数O(n),即时间复杂度为O(nlogn);

解法三:排序O(nlogn)

前边解法二我们已经进行了简单的分析,那么我们再换个角度想想,当我们排序好了后,对于出现频率大于50%的数来说,排序后是不是一定会横跨下标为N/2的点,那么我们在排序后还用计数吗?

显然不用,那么时间复杂度就为O(nlogn)+O(1),即O(nlogn)
(是不是又有了进步了,在这里你有没有感觉到算法的奥秘了呢?)

额,好吧,我忽略了一个问题,关于时间复杂度的分析。
请各位朋友查看时间复杂度、算法时间复杂度的表示法、为什么见周围人描述算法复杂度都用大 O 符号而不是大 Θ?

解法四:桶排序的应用O(n)

相信大家在查看了八大排序算法后,肯定或多或少的看过了关于桶排序的思想及实现。
那么我们在解答此题目的时候就可以用桶排序来应用解答了,时间复杂度即为 桶排序O(n)+遍历查找O(n),即时间复杂度为O(n).
是不是感觉我们在时间复杂度方面进行了质的飞跃,

A:对的,我们从最开始的O(n*n),然后到O(nlogn),直到现在的O(n)
Q:哇,看来桶排序算法这么好,但是桶排序算法是需要开辟一个很大的数组(很大就是这堆数中最大的那个数那么大),岂不是很浪费空间,而且还可能直接爆内存呢?
A:看来你是认真的看了前边的排序,而且对于桶排序的优缺点有了一定的认识,那么我们接下来进行相应的改造吧。
Q:怎么改造呢?
A:对于桶排序来说,其实是将下标来记录我们的元素的大小,那么我们可以通过映射的方式将下标映射为另一个数组的元素值,那么我们不就是解决了上边所说的开辟大数组的空间的矛盾了吗?
Q:噢,这样呀,但是实现起来有点难呀。
A:额,是的哟,这个实现,,,咳咳
Q:不用再说了,肯定又要交给聪明的我来实现了。
A:哈哈哈哈,小伙子有觉悟

如果我们使用映射的方式,其实还有另外的一个好处,那就是我们可以处理大数问题,当这N个数中存在超大超大的数的时候,我们直接用字符串来存储,然后进行相应的映射就可以进行解答主元素问题了。

解法五:抵消法O(n)

终极boss出场了,BGM
对于查找主元素,也就是人们常说的“多数问题”,我们其实并不是很关心其他的元素,我们要求就是找到这个主元素,接下来简单的讲下这个极其优雅的算法:

遍历整个存放N个数的数组,当碰到有两个数不相等时,删除两数,最后剩下的数就是主元素。

Q:完了?
A:完了。
Q:。。。

不懂的朋友请看友情链接。
寻找数组的主元素问题的解法、主元素问题、主元素问题求解、主元素问题的绝妙算法

小结:算法妙不可言

相信大家看到这里,对于主元素问题已经了有足够的认识,通过解法一到解法五的层层深入探讨主元素问题,如果你在每一种解法都进行了相应的实现并进行纵向的比对后,相信你会发现通过算法的改进和寻找算法来解答这个问题的过程中,不只是时间复杂度的降低,我们在代码实现以及代码量上边也有了相应的改善,同时,通过转方位转角度的思考一个问题,逻辑思维也得到了相应的锻炼和提高。
在学习算法的过程中,不只是AC的快感,庚重要的是在解题过程中享受的快乐和锻炼的痛感,在思维世界里徜徉的自由之美。

PS:如有什么地方说得不对的,欢迎指正交流。

原创粉丝点击