设计一个找到数据流中第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。
思路分析: 首先我的思路是想着怎么排序,每次都插入一个元素,为此选择插入排序,插入后再返回第k大元素。
class KthLargest {
public:
int k = 1;
list<int> myList;//降序链表
KthLargest(int k, vector<int>& nums) {
this->k = k;
//将所有元素依次插入
for (auto num : nums) {
auto it = myList.begin();
while (it != myList.end() && *it > num) {
it++;
}
it = myList.insert(it, num);
}
}
int add(int val) {
//第一步找到插入的位置
auto it = myList.begin();
while (it != myList.end() && *it > val) {
it++;
}
myList.insert(it, val);//插入
//然后找到第K大元素
it = myList.begin();
int tempK = k;
while (tempK-- > 1) {
it++;
}
return *it;
}
};
/**
* Your KthLargest object will be instantiated and called as such:
* KthLargest* obj = new KthLargest(k, nums);
* int param_1 = obj->add(val);
*/
这样时间复杂度为O(n),空间复杂度为O(n)。
但是在一个已经排好序的元素中插入的应该使用二分法,时间复杂度为O(log2n)。
class KthLargest {
public:
int k = 1;
multiset<int> mySet;//集合自带排序
KthLargest(int k, vector<int>& nums) {
this->k = k;
//将所有元素依次插入
for (auto num : nums) {
mySet.insert(num);
}
}
int add(int val) {
mySet.insert(val);//插入到集合
//获取第K大的元素
auto it = mySet.end();
int tempK = k;
while (tempK-- > 0) {
it--;
}
return *it;
}
};
/**
* Your KthLargest object will be instantiated and called as such:
* KthLargest* obj = new KthLargest(k, nums);
* int param_1 = obj->add(val);
*/
蛋式还是超时了。。
下面将维护一个大小为k的升序优先队列,这队首就是第K大元素。
class KthLargest {
public:
int myK = 1;
priority_queue<int, vector<int>, greater<int>> myPriorityQue;//按降序排列的优先队列
KthLargest(int k, vector<int>& nums) {
myK = k;
//将所有元素依次插入
for (auto num : nums) {
myPriorityQue.push(num);
}
//维持队列的大小为k
while (myPriorityQue.size() > k){
myPriorityQue.pop();
}
}
int add(int val) {
if (myPriorityQue.size() == myK){
//只有当队列大小为k时,才需要考虑是否需要pop元素
if (val > myPriorityQue.top()){
//只有当队首小于val,这val才能该表第K大元素
myPriorityQue.pop();
myPriorityQue.push(val);
}
}
else{
//否则直接放入
myPriorityQue.push(val);
}
return myPriorityQue.top();//当前队首就是第K大元素
}
};
/**
* Your KthLargest object will be instantiated and called as such:
* KthLargest* obj = new KthLargest(k, nums);
* int param_1 = obj->add(val);
*/