⭐算法入门⭐《堆》中等02 —— LeetCode 703. 数据流中的第 K 大元素
文章目录
- 一、题目
- 1、题目描述
- 2、基础框架
- 3、原题链接
- 二、解题报告
- 1、思路分析
- 2、时间复杂度
- 3、代码详解
- 三、本题小知识
- 四、加群须知
一、题目
1、题目描述
设计一个找到数据流中第 k 大元素的类(class)。注意是排序后的第 k 大元素,不是第 k 个不同的元素。请实现 KthLargest 类:
1)KthLargest(int k, int[] nums) 使用整数 k 和整数流 nums 初始化对象。
2)int add(int val) 将 val 插入数据流 nums 后,返回当前数据流中第 k 大的元素。
样例输入:["KthLargest", "add", "add", "add", "add", "add"] [[3, [4, 5, 8, 2]], [3], [5], [10], [9], [4]]
样例输出:[null, 4, 5, 5, 8, 8]
2、基础框架
- C语言 版本给出的基础框架代码如下:
typedef struct {} KthLargest;KthLargest* kthLargestCreate(int k, int* nums, int numsSize) {}int kthLargestAdd(KthLargest* obj, int val) {}void kthLargestFree(KthLargest* obj) {}
3、原题链接
剑指 Offer II 059. 数据流的第 K 大数值
LeetCode 703. 数据流中的第 K 大元素
二、解题报告
1、思路分析
维护一个小顶堆,堆的元素始终保持 kkk 个,那么堆顶的就一定是第 kkk 大的元素。
2、时间复杂度
创建堆的过程为 O(nlog2n)O(nlog_2n)O(nlog2n),每次执行插入,都要执行弹出操作,单次插入删除的时间复杂度为 O(log2n)O(log_2n)O(log2n)。
3、代码详解
/**********************************小顶堆模板************************************/
#define lson(idx) (idx << 1|1)
#define rson(idx) ((idx + 1) << 1)
#define parent(idx) ((idx - 1) >> 1)
#define root 0
#define DataType int// -1 和 1 交换,就变成了大顶堆
int compareData(const DataType* a, const DataType* b) {if(*a < *b) {return -1;}else if(*a > *b) {return 1;}return 0;
}void swap(DataType* a, DataType* b) {DataType tmp = *a;*a = *b;*b = tmp;
}typedef struct {DataType *data;int size;int capacity;
}Heap;// 内部接口,小写驼峰// heapShiftDown 这个接口是一个内部接口,所以用小写驼峰区分,用于对堆中元素进行删除的时候的下沉调整;
void heapShiftDown(Heap* heap, int curr) {int son = lson(curr);while(son < heap->size) {if( rson(curr) < heap->size ) {if( compareData( &heap->data[rson(curr)], &heap->data[son] ) < 0 ) {son = rson(curr); // 始终选择值更小的结点} }if( compareData( &heap->data[son], &heap->data[curr] ) < 0 ) {swap(&heap->data[son], &heap->data[curr]); // 子结点的值小于父结点,则执行交换;curr = son;son = lson(curr);}else {break; // 子结点的值大于父结点,说明已经正确归位,下沉操作结束,跳出循环;}}
}// heapShiftUp 这个接口是一个内部接口,所以用小写驼峰区分,用于对堆中元素进行插入的时候的上浮调整;
void heapShiftUp(Heap* heap, int curr) {int par = parent(curr);while(par >= root) {if( compareData( &heap->data[curr], &heap->data[par] ) < 0 ) {swap(&heap->data[curr], &heap->data[par]); // 子结点的值小于父结点,则执行交换;curr = par;par = parent(curr);}else {break; // 子结点的值大于父结点,说明已经正确归位,上浮操作结束,跳出循环;}}
}bool heapIsFull(Heap *heap) {return heap->size == heap->capacity;
}// 外部接口,大写驼峰// 堆的判空
bool HeapIsEmpty(Heap *heap) {return heap->size == 0;
}int HeapSize(Heap *heap) {return heap->size;
}// 堆的插入
// 插到最后一个位置,然后不断进行上浮操作
bool HeapPush(Heap* heap, DataType data) {if( heapIsFull(heap) ) {return false;}heap->data[ heap->size++ ] = data;heapShiftUp(heap, heap->size-1);return true;
}// 堆的删除
// 1、删除堆顶元素时,将堆底部的下标最大的元素放入对顶;
// 2、然后调用 shiftDown 将这个元素进行下沉操作;
// 对于小顶堆来说,从根到叶子的路径必然是单调不降的,所以下沉操作一定会终止在路径的某个点,并且保证所有的堆路径还是能够维持单调不降;
bool HeapPop(Heap *heap) {if(HeapIsEmpty(heap)) {return false;}heap->data[root] = heap->data[ --heap->size ];heapShiftDown(heap, root);return true;
}DataType HeapTop(Heap *heap) {assert(!HeapIsEmpty(heap));return heap->data[root];
}// 创建堆
Heap* HeapCreate(DataType *data, int dataSize, int maxSize) {int i;Heap *h = (Heap *)malloc( sizeof(Heap) );h->data = (DataType *)malloc( sizeof(DataType) * maxSize );h->size = 0;h->capacity = maxSize;for(i = 0; i < dataSize; ++i) {HeapPush(h, data[i]);}return h;
}// 销毁堆
void HeapFree(Heap *heap) {free(heap->data);free(heap);
}/**********************************小顶堆模板************************************/typedef struct {Heap *heap;int K;
} KthLargest;KthLargest* kthLargestCreate(int k, int* nums, int numsSize) {KthLargest *KL = (KthLargest *)malloc( sizeof(KthLargest) );KL->K = k;KL->heap = HeapCreate(nums, numsSize, 100000); // (1)return KL;
}int kthLargestAdd(KthLargest* obj, int val) {HeapPush(obj->heap, val);while(HeapSize(obj->heap) > obj->K) { // (2)HeapPop(obj->heap);}return HeapTop(obj->heap);
}void kthLargestFree(KthLargest* obj) {HeapFree(obj->heap);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);
*/
- (1)(1)(1) 创建一个小顶堆;
- (2)(2)(2) 维持堆元素个数始终为 kkk 个;
三、本题小知识
堆 可以用于实现 KKK 大数。
四、加群须知
相信看我文章的大多数都是「 大学生 」,能上大学的都是「 精英 」,那么我们自然要「 精益求精 」,如果你还是「 大一 」,那么太好了,你拥有大把时间,当然你可以选择「 刷剧 」,然而,「 学好算法 」,三年后的你自然「 不能同日而语 」。
那么这里,我整理了「 几十个基础算法 」 的分类,点击开启:
703. 数据流中的第K大元素 设计一个找到数据流中第K大元素的类(class).注意是排序后的第K大元素,不是第K个不同的元素. 你的 KthLargest 类需要一个同时接收整数 k 和整数数组n ... 如题: 设计一个找到数据流中第K大元素的类(class).注意是排序后的第K大元素,不是第K个不同的元素. 你的 KthLargest 类需要一个同时接收整数 k 和整数数组nums 的构造器,它包含 ... 设计一个找到数据流中第 k 大元素的类(class).注意是排序后的第 k 大元素,不是第 k 个不同的元素. 请实现 KthLargest 类: KthLargest(int k, int[] nu ... 1. 题目 设计一个找到数据流中第K大元素的类(class). 注意是排序后的第K大元素,不是第K个不同的元素. 你的 KthLargest 类需要一个同时接收整数 k 和整数数组nums 的构造器, ... 解题思路: 使用一个最小堆来存储数据,在C++中,对应是#include<queue>头文件中的priority_queue. 程序逻辑:KthLargest类初始化的时候,先根据nums ... 703. 数据流中的第 K 大元素: 题目链接 :[703. 数据流中的第 K 大元素]https://leetcode-cn.com/problems/kth-largest-element-in- ... 一些恶魔抓住了公主(P)并将她关在了地下城的右下角.地下城是由 M x N 个房间组成的二维网格.我们英勇的骑士(K)最初被安置在左上角的房间里,他必须穿过地下城并通过对抗恶魔来拯救公主. 骑士的初始 ... 前言 在这里给自己打个广告,需要的小伙伴请自行订阅. python快速学习实战应用系列课程 https://blog.csdn.net/wenyusuran/category_2239261.html ... 设计一个找到数据流中第K大元素的类(class).注意是排序后的第K大元素,不是第K个不同的元素. 你的 KthLargest 类需要一个同时接收整数 k 和整数数组nums 的构造器,它包含数据流中 ...⭐算法入门⭐《堆》中等02 —— LeetCode 703. 数据流中的第 K 大元素相关推荐
最新文章
热门文章