鏈接:https://leetcode-cn.com/problems/kth-largest-element-in-a-stream
設計一個找到數據流中第K大元素的類(class)。注意是排序後的第K大元素,不是第K個不同的元素。
你的 KthLargest 類需要一個同時接收整數 k 和整數數組nums 的構造器,它包含數據流中的初始元素。每次調用 KthLargest.add,返回當前數據流中第K大的元素。
示例:
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
說明:
你可以假設 nums 的長度≥ k-1 且k ≥ 1。
改進後:
/* 思路
kthLargestCreate 時候 (快速排序)
add 之後,數據保存在 obj 中
add 之後,obj (直接插入) 不能直接用快排,浪費時間 ..
改進:
用最小堆,會更快一點 , 長度爲 k
*/
void heap_swap(int *a, int *b){
int tmp = *a;
*a = *b;
*b = tmp;
}
void adjust_min_heap(int *nums, int pos, int len){
int tmp = nums[pos]; // 臨時保存根節點
int child = pos * 2 + 1; // 左子葉節點 (右子葉節點不一定存在)
while(child <= len){
pos = (child - 1) / 2;
if(child + 1 <= len && nums[child + 1] > nums[child]){ // 找出左右子結點最大值
child++;
}
if(nums[child] > tmp){ // (葉子)節點上升
nums[pos] = nums[child];
child = child * 2 + 1; // 往下繼續調整
}else{
break; // 跳出循環
}
}
nums[(child - 1) / 2] = tmp;
}
void heap_sort(int *nums, int numsSize){
// 將原始數組調整爲最小堆
int i = 0;
for(i = numsSize / 2 - 1; i >= 0; i--){ // 計算有子葉根節點位置 nums[i]
adjust_min_heap(nums, i, numsSize - 1);
}
// 交換堆頂 ,繼續調整
for(i = numsSize - 1; i > 0; i--){
heap_swap(&nums[0], &nums[i]);
adjust_min_heap(nums, 0, i - 1);
}
}
// 調整最小堆
void heap_insert_head(int *nums, int *len){
int tmp = nums[0];
int pos = 0;
int child = 1;
while(child <= len){
pos = (child - 1) / 2;
if(child + 1 <= len && nums[child] > nums[child + 1]){
child++;
}
if(nums[child] < tmp){
nums[pos] = nums[child];
child = child * 2 +1;
}else{
break;
}
}
nums[(child - 1) / 2] = tmp;
}
/////////////////////////////////////////////////////////////////////////////
typedef struct {
int asize;
int *arr;
int flag;
} KthLargest;
KthLargest* kthLargestCreate(int k, int* nums, int numsSize) {
KthLargest *kl = (KthLargest *)calloc(1, sizeof(KthLargest));
kl->asize = k;
kl->arr = (int *)calloc(1, kl->asize * sizeof(int));
kl->flag = numsSize >= k ? 0 : 1;
int i = 0;
// heap sort nums;
heap_sort(nums, numsSize);
if(0 == numsSize){
kl->flag = 1;
return kl;
}
int len = numsSize >= k ? k : numsSize;
for(i = 0; i < len; i++){ kl->arr[k - 1 - i] = nums[numsSize - 1 - i]; }
return kl;
}
int kthLargestAdd(KthLargest* obj, int val) {
if(val <= obj->arr[0] && !obj->flag){
return obj->arr[0];
}
obj->flag = 0;
obj->arr[0] = val;
heap_insert_head(obj->arr, obj->asize - 1);
return obj->arr[0];
}
void kthLargestFree(KthLargest* obj) {
free(obj->arr);
free(obj);
}
改進前
void quick_sort(int* nums, int start, int end){
if(start >= end){ return; }
int i = start;
int j = end;
while(i < j){
while(nums[j] <= nums[start] && i < j){
j--;
}
while(nums[i] >= nums[start] && i < j){
i++;
}
if(i < j){
int tmp = nums[j];
nums[j] = nums[i];
nums[i] = tmp;
}
}
// 交換基準值
int tmp = nums[start];
nums[start] = nums[i];
nums[i] = tmp;
quick_sort(nums, start, i-1);
quick_sort(nums, i + 1, end);
}
void sort_insert(int *nums, int nums_length) {
int i = 0;
int j = 0;
for (i = 1; i < nums_length; i++) {
int tmp = nums[i];
for (j = i - 1; j >= 0 ; j--) {
if (tmp > nums[j]) {
nums[j + 1] = nums[j];
}
else {
break;
}
}
nums[j + 1] = tmp;
}
}
typedef struct {
int k; // 保存k值
int size; // arr 的長度
int kvalue;// 保存第k個值,提高性能
int *arr;
} KthLargest;
KthLargest* kthLargestCreate(int k, int* nums, int numsSize) {
KthLargest* kl = (KthLargest *)calloc(sizeof(KthLargest), 1);
kl->k = k;
kl->size = numsSize;
kl->arr = (int *)calloc(1, sizeof(int) * numsSize);
// 快排 (從大到小)
quick_sort(nums, 0, numsSize - 1);
kl->kvalue = INT_MIN;
int i = 0;
for(i = 0; i < numsSize; i++){ kl->arr[i] = nums[i]; }
return kl;
}
int kthLargestAdd(KthLargest* obj, int val) {
if(val < obj->kvalue){ return obj->kvalue; } // 提高性能
obj->size = obj->size + 1 > obj->k + 1 ? obj->k + 1 : obj->size + 1;
obj->arr = (int *)realloc(obj->arr, obj->size * sizeof(int));
obj->arr[obj->size - 1] = val;
// 直接插入排序 val
sort_insert(obj->arr, obj->size);
obj->kvalue = obj->arr[obj->k - 1];
return obj->kvalue;
}
void kthLargestFree(KthLargest* obj) {
free(obj->arr);
free(obj);
}
/**
* Your KthLargest struct will be instantiated and called as such:
* KthLargest* obj = kthLargestCreate(k, nums, numsSize);
* int param_1 = kthLargestAdd(obj, val);
* kthLargestFree(obj);
*/