力扣703 数据流中的第 K 大元素(multiset法)

原题:703. 数据流中的第 K 大元素

 

设计一个找到数据流中第 k 大元素的类(class)。注意是排序后的第 k 大元素,不是第 k 个不同的元素。

请实现 KthLargest 类:

KthLargest(int k, int[] nums) 使用整数 k 和整数流 nums 初始化对象。
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]

解释:
KthLargest kthLargest = new KthLargest(3, [4, 5, 8, 2]);
kthLargest.add(3);   // return 4
kthLargest.add(5);   // return 5
kthLargest.add(10);  // return 5
kthLargest.add(9);   // return 8
kthLargest.add(4);   // return 8
 

提示:
1 <= k <= 104
0 <= nums.length <= 104
-104 <= nums[i] <= 104
-104 <= val <= 104
最多调用 add 方法 104 次
题目数据保证,在查找第 k 大元素时,数组中至少有 k 个元素

        显而易见的,找数据流中的第k大元素,是需要排序的。如果不使用任何的数据结构,那么首先对初始的输入nums进行排序,然后依次对插入的数据寻找位置后插入nums中,但实现起来比较慢,效果也并不是很客观。在这里,可以利用multiset的特性,即任意顺序插入的multiset始终是保持有序的(从小到大),并且可以容许数字重复出现,例如依次插入4、5、8、2,在multiset中的顺序为2、4、5、8,这样节省了手动初始排序和后序插入排序的时间。因为要输出第k大元素,那么这个multiset的大小控制为k即可,当插入数据后multiset的大小超过k,那么删除multiset的第一个元素就实现了控制k的大小,并且现在这个multiset的k个元素是输入数据流中最大的k个。

        所以,在KthLargest中,根据初始的nums依次插入muliset中,如果大小超过k,就删除第一个元素。同理,在add中,先插入val,如果大于k,就删除第一个元素(可能初始的数据流大小小于k,所以需要先判断再删除,否则multiset的大小始终小于k),然后再返回删除后的第一个元素即可。在add函数中需要知道大小k,但是在给定的输入参数中并没有,所以定义了一个全局变量kk,来保存k的值。

class KthLargest {
    multiset <int> topk;
    int kk;
public:
    KthLargest(int k, vector<int>& nums) {
        kk=k;
        for(int i=0;i<nums.size();i++){
            topk.insert(nums[i]);
            if(topk.size()>k)
                topk.erase(topk.begin());
        }
    }
    
    int add(int val) {
        topk.insert(val);
        if(topk.size()>kk)
            topk.erase(topk.begin());
        return *topk.begin();
    }
};

/**
 * Your KthLargest object will be instantiated and called as such:
 * KthLargest* obj = new KthLargest(k, nums);
 * int param_1 = obj->add(val);
 */

猜你喜欢

转载自blog.csdn.net/qq_36614557/article/details/114263559