成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

每日算法:前 K 個(gè)高頻元素

開發(fā) 前端 算法
桶排序 (Bucket sort)的工作的原理:假設(shè)輸入數(shù)據(jù)服從均勻分布,將數(shù)據(jù)分到有限數(shù)量的桶里,每個(gè)桶再分別排序(有可能再使用別的排序算法或是以遞歸方式繼續(xù)使用桶排序進(jìn)行排)。

 

給定一個(gè)非空的整數(shù)數(shù)組,返回其中出現(xiàn)頻率前 k 高的元素。

示例 1:

  1. 輸入: nums = [1,1,1,2,2,3], k = 2 
  2. 輸出: [1,2] 

示例 2:

  1. 輸入: nums = [1], k = 1 
  2. 輸出: [1] 

提示:

  • 你可以假設(shè)給定的 k 總是合理的,且 1 ≤ k ≤ 數(shù)組中不相同的元素的個(gè)數(shù)。
  • 你的算法的時(shí)間復(fù)雜度必須優(yōu)于 O(nlogn) , n 是數(shù)組的大小。
  • 題目數(shù)據(jù)保證答案唯一,換句話說,數(shù)組中前 k 個(gè)高頻元素的集合是唯一的。
  • 你可以按任意順序返回答案。

解法一:map+數(shù)組

利用 map 記錄每個(gè)元素出現(xiàn)的頻率,利用數(shù)組來比較排序元素

代碼實(shí)現(xiàn):

  1. let topKFrequent = function(nums, k) { 
  2.     let map = new Map(), arr = [...new Set(nums)] 
  3.     nums.map((num) => { 
  4.         if(map.has(num)) map.set(num, map.get(num)+1) 
  5.         else map.set(num, 1) 
  6.     }) 
  7.      
  8.     return arr.sort((a, b) => map.get(b) - map.get(a)).slice(0, k); 
  9. }; 

復(fù)雜度分析:

  • 時(shí)間復(fù)雜度:O(nlogn)
  • 空間復(fù)雜度:O(n)

題目要求算法的時(shí)間復(fù)雜度必須優(yōu)于 O(n log n) ,所以這種實(shí)現(xiàn)不合題目要求

解法二:map + 小頂堆

遍歷一遍數(shù)組統(tǒng)計(jì)每個(gè)元素的頻率,并將元素值( key )與出現(xiàn)的頻率( value )保存到 map 中

通過 map 數(shù)據(jù)構(gòu)建一個(gè)前 k 個(gè)高頻元素小頂堆,小頂堆上的任意節(jié)點(diǎn)值都必須小于等于其左右子節(jié)點(diǎn)值,即堆頂是最小值。

具體步驟如下:

  • 遍歷數(shù)據(jù),統(tǒng)計(jì)每個(gè)元素的頻率,并將元素值( key )與出現(xiàn)的頻率( value )保存到 map 中
  • 遍歷 map ,將前 k 個(gè)數(shù),構(gòu)造一個(gè)小頂堆
  • 從 k 位開始,繼續(xù)遍歷 map ,每一個(gè)數(shù)據(jù)出現(xiàn)頻率都和小頂堆的堆頂元素出現(xiàn)頻率進(jìn)行比較,如果小于堆頂元素,則不做任何處理,繼續(xù)遍歷下一元素;如果大于堆頂元素,則將這個(gè)元素替換掉堆頂元素,然后再堆化成一個(gè)小頂堆。
  • 遍歷完成后,堆中的數(shù)據(jù)就是前 k 大的數(shù)據(jù)

代碼實(shí)現(xiàn):

  1. let topKFrequent = function(nums, k) { 
  2.     let map = new Map(), heap = [,] 
  3.     nums.map((num) => { 
  4.         if(map.has(num)) map.set(num, map.get(num)+1) 
  5.         else map.set(num, 1) 
  6.     }) 
  7.      
  8.     // 如果元素?cái)?shù)量小于等于 k 
  9.     if(map.size <= k) { 
  10.         return [...map.keys()] 
  11.     } 
  12.      
  13.     // 如果元素?cái)?shù)量大于 k,遍歷map,構(gòu)建小頂堆 
  14.     let i = 0 
  15.     map.forEach((value, key) => { 
  16.         if(i < k) { 
  17.             // 取前k個(gè)建堆, 插入堆 
  18.             heap.push(key
  19.             // 原地建立前 k 堆 
  20.             if(i === k-1) buildHeap(heap, map, k) 
  21.         } else if(map.get(heap[1]) < value) { 
  22.             // 替換并堆化 
  23.             heap[1] = key 
  24.             // 自上而下式堆化第一個(gè)元素 
  25.             heapify(heap, map, k, 1) 
  26.         } 
  27.         i++ 
  28.     }) 
  29.     // 刪除heap中第一個(gè)元素 
  30.     heap.shift() 
  31.     return heap 
  32. }; 
  33.  
  34. // 原地建堆,從后往前,自上而下式建小頂堆 
  35. let buildHeap = (heap, map, k) => { 
  36.     if(k === 1) return 
  37.     // 從最后一個(gè)非葉子節(jié)點(diǎn)開始,自上而下式堆化 
  38.     for(let i = Math.floor(k/2); i>=1 ; i--) { 
  39.         heapify(heap, map, k, i) 
  40.     } 
  41.  
  42. // 堆化 
  43. let heapify = (heap, map, k, i) => { 
  44.     // 自上而下式堆化 
  45.     while(true) { 
  46.         let minIndex = i 
  47.         if(2*i <= k && map.get(heap[2*i]) < map.get(heap[i])) { 
  48.             minIndex = 2*i 
  49.         } 
  50.         if(2*i+1 <= k && map.get(heap[2*i+1]) < map.get(heap[minIndex])) { 
  51.             minIndex = 2*i+1 
  52.         } 
  53.         if(minIndex !== i) { 
  54.             swap(heap, i, minIndex) 
  55.             i = minIndex 
  56.         } else { 
  57.             break 
  58.         } 
  59.     } 
  60.  
  61. // 交換 
  62. let swap = (arr, i , j) => { 
  63.     let temp = arr[i] 
  64.     arr[i] = arr[j] 
  65.     arr[j] = temp 

復(fù)雜度分析:

  • 時(shí)間復(fù)雜度:遍歷數(shù)組需要 O(n) 的時(shí)間復(fù)雜度,一次堆化需要 O(logk) 時(shí)間復(fù)雜度,所以利用堆求 Top k 問題的時(shí)間復(fù)雜度為 O(nlogk)
  • 空間復(fù)雜度:O(n)

解法三:桶排序

這里取前k個(gè)高頻元素,使用計(jì)數(shù)排序不再適合,在上題目中使用計(jì)數(shù)排序,將 i 元素出現(xiàn)的次數(shù)存儲(chǔ)在 bucket[i] ,但這種存儲(chǔ)不能保證 bucket 數(shù)組上值是有序的,例如 bucket=[0,3,1,2] ,即元素 0 未出現(xiàn),元素 1 出現(xiàn) 3 次,元素 2 出現(xiàn) 1 次,元素 3 出現(xiàn) 2 次,所以計(jì)數(shù)排序不適用于取前k個(gè)高頻元素,不過,不用怕,計(jì)數(shù)排序不行,還有桶排序。

桶排序是計(jì)數(shù)排序的升級(jí)版。它也是利用函數(shù)的映射關(guān)系。

桶排序 (Bucket sort)的工作的原理:假設(shè)輸入數(shù)據(jù)服從均勻分布,將數(shù)據(jù)分到有限數(shù)量的桶里,每個(gè)桶再分別排序(有可能再使用別的排序算法或是以遞歸方式繼續(xù)使用桶排序進(jìn)行排)。

  • 首先使用 map 來存儲(chǔ)頻率
  • 然后創(chuàng)建一個(gè)數(shù)組(有數(shù)量的桶),將頻率作為數(shù)組下標(biāo),對(duì)于出現(xiàn)頻率不同的數(shù)字集合,存入對(duì)應(yīng)的數(shù)組下標(biāo)(桶內(nèi))即可。

代碼實(shí)現(xiàn):

  1. let topKFrequent = function(nums, k) { 
  2.     let map = new Map(), arr = [...new Set(nums)] 
  3.     nums.map((num) => { 
  4.         if(map.has(num)) map.set(num, map.get(num)+1) 
  5.         else map.set(num, 1) 
  6.     }) 
  7.      
  8.     // 如果元素?cái)?shù)量小于等于 k 
  9.     if(map.size <= k) { 
  10.         return [...map.keys()] 
  11.     } 
  12.      
  13.     return bucketSort(map, k) 
  14. }; 
  15.  
  16. // 桶排序 
  17. let bucketSort = (map, k) => { 
  18.     let arr = [], res = [] 
  19.     map.forEach((value, key) => { 
  20.         // 利用映射關(guān)系(出現(xiàn)頻率作為下標(biāo))將數(shù)據(jù)分配到各個(gè)桶中 
  21.         if(!arr[value]) { 
  22.             arr[value] = [key
  23.         } else { 
  24.             arr[value].push(key
  25.         } 
  26.     }) 
  27.     // 倒序遍歷獲取出現(xiàn)頻率最大的前k個(gè)數(shù) 
  28.     for(let i = arr.length - 1;i >= 0 && res.length < k;i--){ 
  29.         if(arr[i]) { 
  30.             res.push(...arr[i]) 
  31.         } 
  32.  } 
  33.  return res 

復(fù)雜度分析:

  • 時(shí)間復(fù)雜度:O(n)
  • 空間復(fù)雜度:O(n)

leetcode:https://leetcode-cn.com/problems/top-k-frequent-elements/solution/javascript-qian-k-ge-gao-pin-yuan-su-by-user7746o/ 

責(zé)任編輯:武曉燕 來源: 三分鐘學(xué)前端
相關(guān)推薦

2025-04-03 09:56:40

Python算法開發(fā)

2021-09-08 09:52:34

語(yǔ)言

2021-10-29 07:25:32

螺旋矩陣整數(shù)

2021-11-12 09:44:03

字符串算法復(fù)雜度

2021-11-19 07:54:40

前端

2021-10-28 19:33:36

矩陣圖像內(nèi)存

2021-08-30 14:34:10

有效算法字符

2020-08-16 12:38:32

Python算法編程

2018-11-08 16:18:07

JavaScript前端

2021-09-03 09:41:36

字符串時(shí)間復(fù)雜度

2021-11-04 09:59:03

動(dòng)態(tài)規(guī)劃策略

2021-09-30 09:58:14

路徑總和二叉樹

2021-12-07 06:55:17

節(jié)流函數(shù)Throttle

2021-09-29 10:19:00

算法平衡二叉樹

2021-10-27 10:43:36

數(shù)據(jù)流中位數(shù)偶數(shù)

2021-12-09 10:57:19

防抖函數(shù) Debounce

2014-11-28 16:08:33

射頻識(shí)別RFID

2021-09-10 08:31:54

翻轉(zhuǎn)字符串單詞

2021-11-02 10:10:38

面試元素語(yǔ)言

2021-09-02 09:22:13

算法無重復(fù)字符
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 成人av片在线观看 | 亚洲精品电影在线观看 | 精品国产成人 | 国产精品美女 | 妞干网视频 | 鸡毛片| 久久69精品久久久久久国产越南 | 国产高清一区二区三区 | 久久33| 亚洲精品自在在线观看 | 亚洲在线视频 | 99精品在线 | 国产高清视频一区 | 国产黄色大片 | 亚洲欧美一区二区三区1000 | 日韩精品欧美精品 | 国产高清在线精品一区二区三区 | 国产欧美精品一区二区色综合 | 国产1页| 国产亚洲精品久久午夜玫瑰园 | 色婷婷av一区二区三区软件 | 免费成人高清在线视频 | 中文字幕一区二区三区不卡在线 | 青青久久| 天天激情综合 | 欧美a在线看 | 蜜桃视频在线观看免费视频网站www | 中文字幕视频在线观看 | 亚洲一区国产精品 | 久久久精彩视频 | 韩日av在线 | 午夜在线视频 | 欧美日韩在线免费观看 | 国产玖玖 | 精品免费国产一区二区三区 | 在线观看成人小视频 | 午夜在线视频一区二区三区 | 成人午夜激情 | 日本一二区视频 | 国产精品999 | 深夜爽视频 |