陣列中的第K個最大元素
阿新 • • 發佈:2020-08-13
陣列中的第K個最大元素
在未排序的陣列中找到第k
個最大的元素。請注意,你需要找的是陣列排序後的第k
個最大的元素,而不是第k
個不同的元素。
示例
輸入: [3,2,1,5,6,4] 和 k = 2
輸出: 5
輸入: [3,2,3,1,2,4,5,5,6] 和 k = 4
輸出: 4
題解
/** * @param {number[]} nums * @param {number} k * @return {number} */ var findKthLargest = function(arr, k) { var adjustHeap = function(arr, i, n) { for(let k=2*i+1; k<n; k=2*k+1){ let parent = arr[i]; if(k+1 < n && arr[k] < arr[k+1]) ++k; if(parent < arr[k]){ [arr[i], arr[k]] = [arr[k], arr[i]]; i = k; }else{ break; } } } var n = arr.length; for(let i = Math.floor(n/2-1); i>=0; --i) adjustHeap(arr, i, n); var target = 0; for(let i=n-1; i>=n-k; --i){ target = arr[0]; if(i-1>=n-k){ [arr[0], arr[i]] = [arr[i], arr[0]]; adjustHeap(arr, 0, i); } } return target; };
思路
採用大頂堆的資料結構解決問題,大頂堆要求根節點的關鍵字既大於或等於左子樹的關鍵字值,又大於或等於右子樹的關鍵字值並且為完全二叉樹,首先定義adjustHeap
函式左調整堆使用,首先以i
作為雙親元素的下標,以k
作為左孩子的下標,當右孩子存在時判斷右孩子是否大於左孩子,大於左孩子則將k
作為右孩子的指向下標,然後判斷雙親值與k
指向的孩子的節點值的大小,如果孩子值大於雙親值則交換,並且以k
作為雙親節點沿著路徑繼續向下調整,否則就結束本次迴圈,然後定義n
作為陣列長度,之後將堆中每個作為雙親節點的子樹進行調整,使整個樹符合大頂堆的特徵,之後進行k
次迴圈,由於是大頂堆且已調整完成將頂堆的頂值也就是最大值取出賦值給target
k
次即可完成。
每日一題
https://github.com/WindrunnerMax/EveryDay
參考
https://leetcode-cn.com/problems/kth-largest-element-in-an-array/