0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

如何解決數(shù)據(jù)結(jié)構(gòu)設(shè)計最大頻率棧問題?

算法與數(shù)據(jù)結(jié)構(gòu) ? 來源:labuladong ? 作者:labuladong ? 2021-03-02 11:02 ? 次閱讀

讀完本文,可以去力扣解決如下題目:

895.最大頻率棧(Hard)

我個人很喜歡設(shè)計特殊數(shù)據(jù)結(jié)構(gòu)的問題,畢竟在工作中會經(jīng)常用到基本數(shù)據(jù)結(jié)構(gòu),而設(shè)計類的問題就非??简瀸緮?shù)據(jù)結(jié)構(gòu)的理解和運用。

力扣第 895 題要求我們實現(xiàn)一個特殊的數(shù)據(jù)結(jié)構(gòu)「最大頻率?!?,比較有意思,讓我們實現(xiàn)下面這兩個 API

class FreqStack {

// 在棧中加入一個元素 val

public void push(int val) {}

// 從棧中刪除并返回出現(xiàn)頻率最高的元素

// 如果頻率最高的元素不止一個,

// 則返回最近添加的那個元素

public int pop() {}

}

比如下面這個例子:

FreqStack stk = new FreqStack();

// 向最大頻率棧中添加元素

stk.push(2); stk.push(7); stk.push(2);

stk.push(7); stk.push(2); stk.push(4);

// 棧中元素:[2,7,2,7,2,4]

stk.pop() // 返回 2

// 因為 2 出現(xiàn)了三次

// 棧中元素:[2,7,2,7,4]

stk.pop() // 返回 7

// 2 和 7 都出現(xiàn)了兩次,但 7 是最近添加的

// 棧中元素:[2,7,2,4]

stk.pop() // 返回 2

// 棧中元素:[2,7,4]

stk.pop() // 返回 4

// 棧中元素:[2,7]

這種設(shè)計數(shù)據(jù)結(jié)構(gòu)的問題,主要是要搞清楚問題的難點在哪里,然后結(jié)合各種基本數(shù)據(jù)結(jié)構(gòu)的特性,高效實現(xiàn)題目要求的 API。

那么,我們仔細(xì)思考一下 push 和 pop 方法,難點如下:

1、每次 pop 時,必須要知道頻率最高的元素是什么。

2、如果頻率最高的元素有多個,還得知道哪個是最近 push 進(jìn)來的元素是哪個。

為了實現(xiàn)上述難點,我們要做到以下幾點:

1、肯定要有一個變量 maxFreq 記錄當(dāng)前棧中最高的頻率是多少。

2、我們得知道一個頻率 freq 對應(yīng)的元素有哪些,且這些元素要有時間順序。

3、隨著 pop 的調(diào)用,每個 val 對應(yīng)的頻率會變化,所以還得維持一個映射記錄每個 val 對應(yīng)的 freq。

綜上,我們可以先實現(xiàn) FreqStack 所需的數(shù)據(jù)結(jié)構(gòu):

class FreqStack {

// 記錄 FreqStack 中元素的最大頻率

int maxFreq = 0;

// 記錄 FreqStack 中每個 val 對應(yīng)的出現(xiàn)頻率,后文就稱為 VF 表

HashMap《Integer, Integer》 valToFreq = new HashMap《》();

// 記錄頻率 freq 對應(yīng)的 val 列表,后文就稱為 FV 表

HashMap《Integer, Stack《Integer》》 freqToVals = new HashMap《》();

}

其實這有點類似前文 手把手實現(xiàn) LFU 算法,注意 freqToVals 中 val 列表用一個棧實現(xiàn),如果一個 freq 對應(yīng)的元素有多個,根據(jù)棧的特點,可以首先取出最近添加的元素。

要記住在 push 和 pop 方法中同時修改 maxFreq、VF 表、FV 表,否則容易出現(xiàn) bug。

現(xiàn)在,我們可以來實現(xiàn) push 方法了:

public void push(int val) {

// 修改 VF 表:val 對應(yīng)的 freq 加一

int freq = valToFreq.getOrDefault(val, 0) + 1;

valToFreq.put(val, freq);

// 修改 FV 表:在 freq 對應(yīng)的列表加上 val

freqToVals.putIfAbsent(freq, new Stack《》());

freqToVals.get(freq).push(val);

// 更新 maxFreq

maxFreq = Math.max(maxFreq, freq);

}

pop 方法的實現(xiàn)也非常簡單:

public int pop() {

// 修改 FV 表:pop 出一個 maxFreq 對應(yīng)的元素 v

Stack《Integer》 vals = freqToVals.get(maxFreq);

int v = vals.pop();

// 修改 VF 表:v 對應(yīng)的 freq 減一

int freq = valToFreq.get(v) - 1;

valToFreq.put(v, freq);

// 更新 maxFreq

if (vals.isEmpty()) {

// 如果 maxFreq 對應(yīng)的元素空了

maxFreq--;

}

return v;

}

這樣,兩個 API 都實現(xiàn)了,算法執(zhí)行過程如下:

嗯,這道題就解決了,Hard 難度的題目也不過如此嘛~

原文標(biāo)題:數(shù)據(jù)結(jié)構(gòu)基本功:設(shè)計最大頻率棧

文章出處:【微信公眾號:算法與數(shù)據(jù)結(jié)構(gòu)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

責(zé)任編輯:haq

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 數(shù)據(jù)
    +關(guān)注

    關(guān)注

    8

    文章

    6715

    瀏覽量

    88308
  • API
    API
    +關(guān)注

    關(guān)注

    2

    文章

    1461

    瀏覽量

    61489

原文標(biāo)題:數(shù)據(jù)結(jié)構(gòu)基本功:設(shè)計最大頻率棧

文章出處:【微信號:TheAlgorithm,微信公眾號:算法與數(shù)據(jù)結(jié)構(gòu)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    EMC(電磁兼容性)結(jié)構(gòu)設(shè)計基礎(chǔ)

    介紹了電磁兼容的基本定義,要求,結(jié)構(gòu)設(shè)計的準(zhǔn)則和方法。
    發(fā)表于 08-08 14:23 ?12次下載

    5針M16接口結(jié)構(gòu)設(shè)計

    德索工程師說道5針M16接口的結(jié)構(gòu)設(shè)計是一個綜合性的過程,它融合了電氣、機(jī)械、材料科學(xué)等多個領(lǐng)域的知識,旨在提供高效、穩(wěn)定且可靠的電氣連接。以下是對5針M16接口結(jié)構(gòu)設(shè)計的詳細(xì)解析:   5針
    的頭像 發(fā)表于 08-03 09:38 ?197次閱讀
    5針M16接口<b class='flag-5'>結(jié)構(gòu)設(shè)計</b>

    3針M5插座結(jié)構(gòu)設(shè)計

       德索工程師說道在電子設(shè)備和電氣系統(tǒng)中,插座作為連接電源、信號線等的重要接口,其結(jié)構(gòu)設(shè)計對于設(shè)備的整體性能、穩(wěn)定性和安全性具有至關(guān)重要的作用。3針M5插座作為其中一種常見的插座類型,其設(shè)計不僅
    的頭像 發(fā)表于 05-11 17:49 ?336次閱讀
    3針M5插座<b class='flag-5'>結(jié)構(gòu)設(shè)計</b>

    FPGA設(shè)計中,對SPI進(jìn)行參數(shù)化結(jié)構(gòu)設(shè)計

    今天給大俠帶來FPGA設(shè)計中,對SPI進(jìn)行參數(shù)化結(jié)構(gòu)設(shè)計,話不多說,上貨。 為了避免每次SPI驅(qū)動重寫,直接參數(shù)化,盡量一勞永逸。SPI master有啥用呢,你發(fā)現(xiàn)各種外圍芯片的配置一般
    發(fā)表于 05-07 16:09

    7芯M9插頭需采用彈性結(jié)構(gòu)設(shè)計

    德索工程師說道彈性結(jié)構(gòu)設(shè)計可以確保7芯M9插頭與插座之間的良好接觸。在插頭插入插座的過程中,由于制造公差、使用環(huán)境等因素的影響,插頭與插座之間的接觸并不總是完美的。而彈性結(jié)構(gòu)設(shè)計可以通過其自身的彈性
    的頭像 發(fā)表于 04-18 14:29 ?219次閱讀
    7芯M9插頭需采用彈性<b class='flag-5'>結(jié)構(gòu)設(shè)計</b>嗎

    FPGA設(shè)計中,對SPI進(jìn)行參數(shù)化結(jié)構(gòu)設(shè)計

    今天給大俠帶來FPGA設(shè)計中,對SPI進(jìn)行參數(shù)化結(jié)構(gòu)設(shè)計,話不多說,上貨。 為了避免每次SPI驅(qū)動重寫,直接參數(shù)化,盡量一勞永逸。SPI master有啥用呢,你發(fā)現(xiàn)各種外圍芯片的配置一般
    發(fā)表于 04-11 18:29

    TASKING編譯器是否可以將數(shù)據(jù)結(jié)構(gòu)設(shè)置為 \"打包\"?

    TASKING 編譯器是否可以將數(shù)據(jù)結(jié)構(gòu)設(shè)置為 \"打包\"? GCC 很早以前就提供了這種可能性,可以將__attribute__((packed))與對齊指令結(jié)合使用。 對于
    發(fā)表于 03-05 06:00

    異步FIFO結(jié)構(gòu)設(shè)計

    電子發(fā)燒友網(wǎng)站提供《異步FIFO結(jié)構(gòu)設(shè)計.pdf》資料免費下載
    發(fā)表于 02-06 09:06 ?0次下載

    redis數(shù)據(jù)結(jié)構(gòu)的底層實現(xiàn)

    Redis是一種內(nèi)存鍵值數(shù)據(jù)庫,常用于緩存、消息隊列、實時數(shù)據(jù)分析等場景。它的高性能得益于其精心設(shè)計的數(shù)據(jù)結(jié)構(gòu)和底層實現(xiàn)。本文將詳細(xì)介紹Redis常用的數(shù)據(jù)結(jié)構(gòu)和它們的底層實現(xiàn)。 Re
    的頭像 發(fā)表于 12-05 10:14 ?517次閱讀

    不同數(shù)據(jù)結(jié)構(gòu)的定義代碼

    數(shù)據(jù)結(jié)構(gòu)是相互之間存在一種或多種特定關(guān)系的數(shù)據(jù)元素的集合。
    的頭像 發(fā)表于 11-29 14:13 ?535次閱讀

    ringbuffer數(shù)據(jù)結(jié)構(gòu)介紹

    最近在研究srsLTE的代碼,其中就發(fā)現(xiàn)一個有意思的數(shù)據(jù)結(jié)構(gòu)------ringbuffer。 雖然,這是一個很基本的數(shù)據(jù)結(jié)構(gòu),但時,它在LTE這種通信協(xié)議系統(tǒng)中卻大行其道,也是很容易被協(xié)議
    的頭像 發(fā)表于 11-13 10:44 ?1278次閱讀
    ringbuffer<b class='flag-5'>數(shù)據(jù)結(jié)構(gòu)</b>介紹

    epoll的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)

    一、epoll的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu) 在開始研究源代碼之前,我們先看一下 epoll 中使用的數(shù)據(jù)結(jié)構(gòu),分別是 eventpoll、epitem 和 eppoll_entry。 1、eventpoll 我們
    的頭像 發(fā)表于 11-10 10:20 ?630次閱讀
    epoll的基礎(chǔ)<b class='flag-5'>數(shù)據(jù)結(jié)構(gòu)</b>

    Linux內(nèi)核中使用的數(shù)據(jù)結(jié)構(gòu)

    Linux內(nèi)核代碼中廣泛使用了數(shù)據(jù)結(jié)構(gòu)和算法,其中最常用的兩個是鏈表和紅黑樹。 鏈表 Linux內(nèi)核代碼大量使用了鏈表這種數(shù)據(jù)結(jié)構(gòu)。鏈表是在解決數(shù)組不能動態(tài)擴(kuò)展這個缺陷而產(chǎn)生的一種數(shù)據(jù)結(jié)構(gòu)。鏈表所
    的頭像 發(fā)表于 11-09 14:24 ?383次閱讀
    Linux內(nèi)核中使用的<b class='flag-5'>數(shù)據(jù)結(jié)構(gòu)</b>

    一種新型線性自動跟蹤工頻陷波器的電路結(jié)構(gòu)設(shè)計

    電子發(fā)燒友網(wǎng)站提供《一種新型線性自動跟蹤工頻陷波器的電路結(jié)構(gòu)設(shè)計.pdf》資料免費下載
    發(fā)表于 10-23 10:11 ?1次下載
    一種新型線性自動跟蹤工頻陷波器的電路<b class='flag-5'>結(jié)構(gòu)設(shè)計</b>

    SoC系統(tǒng)中的軟件結(jié)構(gòu)設(shè)計

    在一個SoC的系統(tǒng)結(jié)構(gòu)設(shè)計中,除了硬件結(jié)構(gòu)以外,軟件結(jié)構(gòu)的設(shè)計對整個SoC的性能有很大的影響。
    的頭像 發(fā)表于 09-25 15:14 ?869次閱讀