1. 程式人生 > >LeetCode:703. Kth Largest Element in a Stream

LeetCode:703. Kth Largest Element in a Stream

Problem Description

Design a class to find the kth largest element in a stream. Note that it is the kth largest element in the sorted order, not the kth distinct element.

Your KthLargest class will have a constructor which accepts an integer k and an integer array nums, which contains initial elements from the stream. For each call to the method KthLargest.add, return the element representing the kth largest element in the stream.

Example:

int k = 3;
int[] arr = [4,5,8,2];
KthLargest kthLargest = new KthLargest(3, arr);
kthLargest.add(3); // returns 4
kthLargest.add(5); // returns 5
kthLargest.add(10); // returns 5
kthLargest.add(9); // returns 8
kthLargest.add(4); // returns 8
Note:
You may assume that nums’ length ≥ k-1 and k ≥ 1.

題目大意

給定數字k,和一組資料,每次插入一個數,得到插入後這組資料中的第k大元素

解題思路

維護一個大小為k的小頂堆,第k大元素,即為堆頂元素。

同樣,求第k小元素時,只需要維護一個大小為k的大頂堆即可,堆頂元素即為第k小元素

資料結構:堆

堆的特點:
首先堆是一棵完全二叉樹
其次,堆分為大頂堆和小頂堆

大頂堆:父節點大於兩個子節點
小頂堆:父節點小於兩個子節點

例如:這是一個小頂堆,假設遍歷100個整數得到這個大小為14的小頂堆,則堆頂的1是這100個整數的第14大元素。
小頂堆示例

實現程式碼

public class KthLargest {

    private
int [] heap;//小頂堆 private int count;//堆中元素個數 private int max;//最大元素個數,即最大k個的小頂堆,堆頂元素為第K大元素 /** * 初始化堆 * @param k 求第k大元素 * @param nums 初始資料 */ public KthLargest(int k, int[] nums) { this.count = 0; this.max = k; this.heap = new int [k+1]; for(int i=0; i<nums.length; i++){ insert(nums[i]); } } public int add(int val) { insert(val); return this.heap[1]; } /** * 堆中插入元素 * @param data 插入的資料 */ private void insert(int data) { //堆中資料滿了,則判斷是否替換堆頂元素,未滿,則直接插入到堆尾 if(this.count >= this.max){ if(this.heap[1] < data){ this.heap[1] = data; } else { return; } //自上而下堆化 int i=1; while(true){ int left = 2*i; int right = 2*i+1; int minPor = i; if(left <= this.max && this.heap[left] < data){ minPor = left; } if(right <= this.max && this.heap[right] < this.heap[minPor]){ minPor = right; } if(minPor == i) break; else swap(i, minPor); i = minPor; } } else { this.heap[++this.count] = data; int i = this.count; //自下而上堆化 while(i/2 > 0 && this.heap[i] < this.heap[i/2]){ swap(i, i/2); i = i/2; } } } /** * 交換兩個數 * @param i * @param j */ private void swap(int i, int j) { this.heap[i] = this.heap[i] ^ this.heap[j]; this.heap[j] = this.heap[i] ^ this.heap[j]; this.heap[i] = this.heap[i] ^ this.heap[j]; } public static void main(String[] args) { int k = 7; int[] arr = new int[] {-10,1,3,1,4,10,3,9,4,5,1}; KthLargest kthLargest = new KthLargest(k, arr); System.out.println(kthLargest.add(3)); System.out.println(kthLargest.add(11)); System.out.println(kthLargest.add(22)); System.out.println(kthLargest.add(1)); System.out.println(kthLargest.add(55)); } }