Leetcode 239 滑動視窗最大值 與堆排序kotlin語言(超時)
Leetcode 239 滑動視窗最大值 與堆排序kotlin語言(超時)
首先看題目描述:
思路:
被慣性思維害死了。
一眼,哦最大的數字。要排序。再看提示,堆,滑動視窗。懂了 大根堆。
上來就直接一個大根堆,幸虧資料結構學得還行,不然直接碼 真碼不出來。
實現:
首先是堆得部分:
fun BuildMaxHeap(heap:IntArray, lenth:Int){//建立大根堆 順序表儲存 資訊內容儲存在1-n位 0號預留,用作處理
for (i in lenth/2 downTo 1 ) {//自下而上反覆調整堆
HeadAdjust( heap,i,lenth)
}
}
fun HeapInsert(heap:IntArray, lenth:Int, num:Int){//往堆中插入一個數字,該題中堆的大小穩定,故直接給最後位,然後重新建堆即可
heap[lenth] = num
BuildMaxHeap( heap, lenth)
}
fun HeapOut(heap:IntArray, lenth:Int, num:Int){//從堆中刪除一個數字
var templenth = lenth
var which = lenth //它在哪個位置 如果是連結串列儲存的堆需要層次遍歷
for(i in 1 until lenth){
if(heap[i] == num){
which = i
break
}
}
heap[which] = heap[lenth]//把被刪除數和最後的數字調換(但並不用管被刪除數
templenth --
for (j in templenth/2 downTo which) {//自下而上反覆調整堆,最前面穩定的大根堆不需要調整
HeadAdjust( heap, j, templenth)
}
}
fun HeadAdjust(heap:IntArray, k :Int, lenth:Int){//自上而下調整 將元素k為根的子樹進行調整
heap[0] = heap[k] //0號元素暫存子樹的根節點
var root = k
var i = 2 * k
while ( i <= lenth) {//沿著較大的子節點向下篩選
if(i<lenth && heap[i] < heap[i+1]){
i++ //取較大的子節點的下標
}
if(heap[0]>=heap[i])
break; //根節點比左右孩子都大 篩選結束
else{ //孩子節點更大
heap[root] = heap[i] //交換 孩子節點和雙親節點
heap[i] = heap[0]
root = i //修改root值,以便繼續向下篩選
}
i*=2
}
heap[0] = 0
}
具體大根堆得原理:
其實就是一個祖先節點比其後代節點要大的完全二叉樹。
建立大根堆的時候從下往上一一調整直到任何子樹調整為祖先節點都小於其後代節點。
每次插入都插在最後面,從下往上一一調整根的位置。
每次刪除都和最後的元素調換位置,從下往上直到要刪除的位置一一調整位置。
按照教材的說法,在建立過程中時間複雜度為O(n) 每次調整時間複雜度為O(h) 故在最好、最壞和平均情況下,堆排序的時間複雜度為O(log2n)
其次是利用大根堆實現功能:
fun maxSlidingWindow(nums: IntArray, k: Int): IntArray {
val tempArray = IntArray(k)
for (i in 0 until k) {
tempArray[i] = nums[i]
}
val heap = intArrayOf(0)+tempArray
//首先取陣列前k個資料送入待處理,第一位置為0用作調整堆的臨時存放
//關於為什麼不生成一個新的臨時變數 而採取0號位有以下好處:
//1.堆實際上是遵循了一定規則的完全二叉樹,採用順序表儲存對比連結串列可以加快執行速度。
// 以1為開頭,則其左右孩子節點分別為2,3 對應以i為長輩節點,則其左右孩子節點分別為2*i與2*i+1
// 減輕堆的處理負責度
//2.充分利用順序表的隨機讀寫特性,不必額外每次控制生成一個變數,減輕了開銷
BuildMaxHeap( heap, k) //陣列生成堆
val intarray = IntArray(nums.size-k+1)
for( i in 0 .. nums.size-k-1){
intarray[i] = heap[1]
HeapOut(heap,k,nums[i])
HeapInsert(heap,k,nums[i+k])
}
intarray[nums.size - k] = heap[1]
return intarray
}
簡要過程:
就是維護大根堆,然後從大根堆讀出最大值
結果:
太糟糕了,第49個例項,要求我維護大小為5W的大根堆。直接超時
反思:
再仔細想想,任何排序都需要花費較長時間。大根堆的時間複雜度已經算是比較低的了。就思路方面絕對沒有問題。
回過頭來就題論題,本題其實並未要求維護一個有序陣列,即並不需要使用排序。況且數字的大小規定為[-10000,10000],這完全可以用hash來做這道題。
總結:
雖然沒有做出題目,但是運用到的資料結構內容也是比較好的。408如果出題不可能出成這樣的。感到惋惜,故留下這篇文章。
相關文章
- LeetCode 239. 滑動視窗最大值LeetCode
- 239. 滑動視窗最大值
- Leetcode 239. 滑動視窗最大值 (Java實現 超詳細註釋!)LeetCodeJava
- 滑動視窗最大值的golang實現Golang
- [Python手撕]滑動視窗最大值Python
- 騰訊面試題-求滑動視窗的最大值面試題
- [Leetcode]雙項佇列解決滑動視窗最大值難題LeetCode佇列
- 滑動視窗法——Leetcode例題LeetCode
- 滑動視窗與雙指標指標
- Go語言實現時間滑動視窗演算法 動態計算增加量、最大值、最小值Go演算法
- 演算法題:返回滑動視窗中的最大值演算法
- 7、滑動視窗套路演算法框架——Go語言版演算法框架Go
- 「LeetCode Top100」之滑動視窗LeetCode
- Sentinel 原理-滑動視窗
- 細聊滑動視窗
- [劍指offer題解][Java]佇列的最大值/滑動視窗的最大值Java佇列
- 程式碼隨想錄 第13天 | ● 239. 滑動視窗最大值 ● 347.前 K 個高頻元素 ● 總結
- Hive實戰—時間滑動視窗計算Hive
- [每日一題] 第二十六題:滑動視窗的最大值每日一題
- 滑動視窗演算法演算法
- Leetcode 最小調整數+滑動視窗遞增子序列LeetCode
- Day10(棧與佇列) | 150. 逆波蘭表示式求值 239. 滑動視窗最大值 347.前 K 個高頻元素佇列
- TCP 流量控制-滑動視窗TCP
- 滑動視窗演算法思路演算法
- Sentinel滑動視窗演算法演算法
- 滑動視窗分析SQL實踐SQL
- 滑動視窗問題總結
- Flink的滾動視窗、會話視窗、滑動視窗及其應用會話
- mysql視窗函式中的滑動視窗MySql函式
- 自己實現一個滑動視窗
- 力扣刷題-滑動視窗(字串)力扣字串
- (轉)leetcode:Find All Anagrams in a String 滑動視窗方法總結LeetCode
- 滑動視窗演算法基本原理與實踐演算法
- WeetCode2滑動視窗系列
- TCP的滑動視窗和擁塞控制TCP
- 程式碼隨想錄刷題day 11 | **150. 逆波蘭表示式求值** **239. 滑動視窗最大值** **347.前 K 個高頻元素**
- 程式碼隨想錄演算法訓練營第23天(補第11天)|150. 逆波蘭表示式求值,239. 滑動視窗最大值演算法
- leetcode刷題記錄:演算法(三)滑動視窗演算法LeetCode演算法