寻找数组中第K频繁的元素
問(wèn)題是:給你一個(gè)數(shù)組,求解出現(xiàn)次數(shù)第K多的元素。當(dāng)然leetcode上的要求是算法復(fù)雜度不能大于O(N*logN)。
首先這個(gè)問(wèn)題我先是在leetcode上看到,當(dāng)時(shí)想了兩種做法,做到一半都覺(jué)得不是很好,正在思考別的方法。然后在牛客網(wǎng)上看別人的面試經(jīng)歷,看到一個(gè)應(yīng)聘者和用我?guī)缀跬耆粯拥乃悸穱L試在面試中解決這個(gè)問(wèn)題(HashMap-->TreeSet),但是都沒(méi)解決出來(lái)。這個(gè)問(wèn)題確實(shí)是一個(gè)乍看不難但是要實(shí)際解決又會(huì)不停發(fā)現(xiàn)自己思路有問(wèn)題的問(wèn)題,于是我索性記錄一下這兩種想法和解決之道。
拿到這個(gè)問(wèn)題的時(shí)候我第一時(shí)間想到了用HashMap解決,鍵值對(duì)的鍵是數(shù)組中的元素的值,值是目前出現(xiàn)的次數(shù),當(dāng)?shù)谝淮纬霈F(xiàn)的時(shí)候值給1,以后發(fā)現(xiàn)已經(jīng)存在那么就取出值加1再放進(jìn)去。這個(gè)方法的思想是用類(lèi)似于上一篇博文中的方法來(lái)做。核心是用hash算法形成一個(gè)元素與儲(chǔ)存位置的映射來(lái)實(shí)現(xiàn)查找操作的常量時(shí)間復(fù)雜度。這么做的結(jié)果是你能在O(N)的算法復(fù)雜度情況下得到一個(gè)HashMap,它儲(chǔ)存了每一種元素和其出現(xiàn)的個(gè)數(shù)。這個(gè)時(shí)候一個(gè)很具體的問(wèn)題就出現(xiàn)了,下一步本來(lái)需要對(duì)出現(xiàn)次數(shù)進(jìn)行一個(gè)排序,然后取出出現(xiàn)次數(shù)第K大的那個(gè)元素。但是問(wèn)題是鍵值對(duì)的映射方式是從鍵映射到值,也就是說(shuō)你用HashMap可以找出值的集合,但是無(wú)法找出與這個(gè)值對(duì)于的鍵。比如你通過(guò)排序知道了最頻繁的次數(shù)是5,但是你不知道到底誰(shuí)出現(xiàn)了5次。這個(gè)地方其實(shí)我要解釋一下,不是說(shuō)你就完全做不到實(shí)現(xiàn)反映射,而是第一,HashMap實(shí)現(xiàn)的是映射你強(qiáng)行根據(jù)值尋找鍵不符合其設(shè)計(jì)初衷,第二,實(shí)現(xiàn)的過(guò)程比較復(fù)雜我想需要很大的算法復(fù)雜度完全抵消了使用HashMap帶來(lái)的好處。比如一個(gè)鍵只能對(duì)應(yīng)一個(gè)值,但是一個(gè)值可能有多個(gè)鍵對(duì)應(yīng)。(每一個(gè)數(shù)組中的元素都有確定的出現(xiàn)次數(shù),但是出現(xiàn)次數(shù)為K的元素可能不止一個(gè))。要解決這些問(wèn)題等等。真的解決了也就不是這道題目的問(wèn)題了。
第二時(shí)間我想到了用TreeSet,因?yàn)樗瓤梢愿鶕?jù)你的重寫(xiě)的equal()方法判斷是否等于和去重,又可以對(duì)你輸入數(shù)據(jù)用comparator進(jìn)行排序。我就想,我干脆寫(xiě)一個(gè)類(lèi),里面即方數(shù)字本身用于比較是否相等(hashcode和equal),又放當(dāng)前出現(xiàn)的次數(shù),又實(shí)現(xiàn)comparator接口來(lái)對(duì)當(dāng)前出現(xiàn)的次數(shù)進(jìn)行排序。我的期望是好的,但是在一開(kāi)始的思考的時(shí)候我忽視了(確實(shí)沒(méi)想到)一個(gè)根本的問(wèn)題,這個(gè)問(wèn)題直接導(dǎo)致我的這個(gè)想法完全不能按照我設(shè)想的實(shí)現(xiàn)。隨著你遍歷的進(jìn)行,你的某個(gè)數(shù)的出現(xiàn)的次數(shù)可能從1變到2變到3。所以你有一個(gè)不停動(dòng)態(tài)修改TreeSet的內(nèi)容對(duì)象的過(guò)程。但是你無(wú)法獲得TreeSet中值為當(dāng)前數(shù)組值的那個(gè)對(duì)象的引用。比如說(shuō)我現(xiàn)在遍歷到數(shù)組中的5這個(gè)元素,于是我去TreeSet中找值為5的對(duì)象,但是找不到(沒(méi)有提供相應(yīng)的方法)。當(dāng)然確實(shí)也不應(yīng)該有這樣的方法,你想你都知道值是5了,可是你又不知道具體引用的值,TreeSet也沒(méi)辦法幫你。如果用遍歷強(qiáng)行去找會(huì)導(dǎo)致一個(gè)很復(fù)雜的過(guò)程,算法復(fù)雜度高(紅黑樹(shù)的遍歷)。同時(shí),TreeSet是按照某種規(guī)律排序的,大量的修改其值的操作(通過(guò)先刪除再add,或者這個(gè)問(wèn)題中的用add覆蓋)會(huì)影響其效率因?yàn)橐S護(hù)某種順序。所以這個(gè)問(wèn)題中也不推薦這么做。
雖然以上兩種做法都么能直接解決這個(gè)問(wèn)題,但是給我?guī)?lái)了思考。
?最后還是做出來(lái)了,大致就是第一種方法不過(guò)鍵值對(duì)的值是我寫(xiě)的類(lèi),最后再用堆排序。這個(gè)做法還是挺蠢得我覺(jué)得。貌似最佳做法使用桶排序O(N)?以后再研究研究這個(gè)。
轉(zhuǎn)載于:https://www.cnblogs.com/dsj2016/p/5501663.html
總結(jié)
以上是生活随笔為你收集整理的寻找数组中第K频繁的元素的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 软件工程的认识
- 下一篇: sql中 in , not in , e