日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

(十)数据结构之“堆”

發(fā)布時間:2023/12/31 编程问答 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 (十)数据结构之“堆” 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

數(shù)據(jù)結(jié)構(gòu)之“堆”

  • 堆是什么?
  • JS中的堆
  • 堆的應(yīng)用
  • 第K個最大元素
  • LeetCode:215.數(shù)組中的第K個最大元素
  • LeetCode:347.前K個高頻元素
  • LeetCode:23.合并K個排序鏈表
  • 思考題

堆是什么?


堆是一種特殊的完全二叉樹
所有的節(jié)點都大于等于(最大堆)或小于等于(最小堆)它的子節(jié)點

JS中的堆

JS中通常用數(shù)組表示堆
左側(cè)子節(jié)點的位置是2 * index + 1
右側(cè)子節(jié)點的位置是2 * index + 2
父節(jié)點位置是( index - 1 ) / 2

堆的應(yīng)用

堆能高效、快速地找出最大值和最小值,時間復(fù)雜度:O(1)
找出第K個最大(最小)元素

第K個最大元素

構(gòu)建一個最小堆,并將元素依次插入堆中
當堆的容量超過K,就刪除堆頂
插入結(jié)束后,堆頂就是第K個最大元素

實現(xiàn)步驟
在類里,生命一個數(shù)組,用來裝元素
主要方法:插入、刪除堆頂、獲取堆頂、獲取堆大小
插入
將值插入堆的底部,即數(shù)組的尾部
然后上移:將這個值和它的父節(jié)點進行交換,直到父節(jié)點小于等于這個插入的值
大小為k的堆中插入元素的時間復(fù)雜度為O(logk)
刪除堆頂
用數(shù)組尾部元素替換堆頂(直接刪除堆頂會破壞堆結(jié)構(gòu))
然后下移:將新堆頂和它的子節(jié)點進行交換,直到子節(jié)點大于等于這個新堆頂
大小為k的堆中刪除堆頂?shù)臅r間復(fù)雜度為O(logk)
獲取堆頂和堆的大小
獲取堆頂:返回數(shù)組的頭部
獲取堆的大小:返回數(shù)組的長度

class MinHeap {constructor() {this.heap = [];}swap(i1, i2) {const temp = this.heap[i1];this.heap[i1] = this.heap[i2];this.heap[i2] = temp;}getParentIndex(i) {//return Math.floor((i - 1) / 2);return (i - 1) >> 1;}getLeftIndex(i) {return i * 2 + 1;}getRightIndex(i) {return i * 2 + 2;}shiftUp(index) {if (index == 0) { return; }const parentIndex = this.getParentIndex(index);if (this.heap[parentIndex] > this.heap[index]) {this.swap(parentIndex, index);this.shiftUp(parentIndex);}}shiftDown(index) {const leftIndex = this.getLeftIndex(index);const rightIndex = this.getRightIndex(index);if (this.heap[leftIndex] < this.heap[index]) {this.swap(leftIndex, index);this.shiftDown(leftIndex);}if (this.heap[rightIndex] < this.heap[index]) {this.swap(rightIndex, index);this.shiftDown(rightIndex);}}//插入insert(value) {this.heap.push(value);this.shiftUp(this.heap.length - 1);}//刪除堆頂pop() {this.heap[0] = this.heap.pop();this.shiftDown(0);}//獲取堆頂peek() {return this.heap[0];}//獲取堆的大小size() {return this.heap.length;} }const h = new MinHeap(); h.insert(3); h.insert(2); h.insert(1); h.pop();

LeetCode:215.數(shù)組中的第K個最大元素

解題思路
看到“第K個最大元素”
考慮選擇使用最小堆
解題步驟
構(gòu)建一個最小堆,并依次把數(shù)組的值插入堆中
當堆的容量超過K,就刪除堆頂
插入結(jié)束后,堆頂就是第K個最大元素

時間復(fù)雜度O(n * logk),空間復(fù)雜度O(k)

LeetCode:347.前K個高頻元素


法一:

時間復(fù)雜度O(n * logn)

法二

class MinHeap {constructor() {this.heap = [];}swap(i1, i2) {const temp = this.heap[i1];this.heap[i1] = this.heap[i2];this.heap[i2] = temp;}getParentIndex(i) {//return Math.floor((i - 1) / 2);return (i - 1) >> 1;}getLeftIndex(i) {return i * 2 + 1;}getRightIndex(i) {return i * 2 + 2;}shiftUp(index) {if (index == 0) { return; }const parentIndex = this.getParentIndex(index);if (this.heap[parentIndex] && this.heap[parentIndex].value > this.heap[index].value) {this.swap(parentIndex, index);this.shiftUp(parentIndex);}}shiftDown(index) {const leftIndex = this.getLeftIndex(index);const rightIndex = this.getRightIndex(index);if (this.heap[leftIndex] && this.heap[leftIndex].value < this.heap[index].value) {this.swap(leftIndex, index);this.shiftDown(leftIndex);}if (this.heap[rightIndex] && this.heap[rightIndex].value < this.heap[index].value) {this.swap(rightIndex, index);this.shiftDown(rightIndex);}}//插入insert(value) {this.heap.push(value);this.shiftUp(this.heap.length - 1);}//刪除堆頂pop() {this.heap[0] = this.heap.pop();this.shiftDown(0);}//獲取堆頂peek() {return this.heap[0];}//獲取堆的大小size() {return this.heap.length;} }

時間O(n * logk),空間O(n)

LeetCode:23.合并K個排序鏈表


解題思路
新鏈表的下一個節(jié)點一定是k個鏈表頭中的最小節(jié)點
考慮選擇使用最小堆
解題步驟
構(gòu)建一個最小堆,并依次把鏈表頭插入堆中
彈出堆頂接到輸出鏈表,并將堆頂所在鏈表的新鏈表頭插入堆中
等堆元素全部彈出,合并工作就完成了

class MinHeap {constructor() {this.heap = [];}swap(i1, i2) {const temp = this.heap[i1];this.heap[i1] = this.heap[i2];this.heap[i2] = temp;}getParentIndex(i) {//return Math.floor((i - 1) / 2);return (i - 1) >> 1;}getLeftIndex(i) {return i * 2 + 1;}getRightIndex(i) {return i * 2 + 2;}shiftUp(index) {if (index == 0) { return; }const parentIndex = this.getParentIndex(index);if (this.heap[parentIndex] && this.heap[parentIndex].val> this.heap[index].val) {this.swap(parentIndex, index);this.shiftUp(parentIndex);}}shiftDown(index) {const leftIndex = this.getLeftIndex(index);const rightIndex = this.getRightIndex(index);if (this.heap[leftIndex] && this.heap[leftIndex].val< this.heap[index].val) {this.swap(leftIndex, index);this.shiftDown(leftIndex);}if (this.heap[rightIndex] && this.heap[rightIndex].val< this.heap[index].val) {this.swap(rightIndex, index);this.shiftDown(rightIndex);}}//插入insert(value) {this.heap.push(value);this.shiftUp(this.heap.length - 1);}//刪除堆頂pop() {if(this.size() === 1) return this.heap.shift();const top = this.heap[0]this.heap[0] = this.heap.pop();this.shiftDown(0);return top;}//獲取堆頂peek() {return this.heap[0];}//獲取堆的大小size() {return this.heap.length;} }


時間復(fù)雜度O(n * logk),n是所有鏈表的節(jié)點數(shù)之和,k是排序鏈表數(shù),空間復(fù)雜度是O(k)

思考題

1、請用堆畫出一場比賽的運動員排名情況,無需 Coding。
2、在 LeetCode 找到一道堆的題目,并通過測試

總結(jié)

以上是生活随笔為你收集整理的(十)数据结构之“堆”的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。