leetcode703.数据流中的第k大元素(解法)

题目描述

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

你的 KthLargest 类需要一个同时接收整数 k 和整数数组nums 的构造器,它包含数据流中的初始元素。每次调用 KthLargest.add,返回当前数据流中第K大的元素。

解法1:优先队列

利用priority_queue这种数据结构。本题中为升序的优先队列,且初始化为有kINT_MIN的队列。add函数的实现为:如果加入的数字小于优先队列的队首,则函数不做处理,返回队首的元素;否则,将队首的元素出队,将该数字加入队列(在push操作中完成对队列重新升序排序)。题目的意图就是每次add函数的返回值就是此时该数据流的第k个最大的元素。

priority_queue补充知识:

1.普通队列具有先进先出的特点。而在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 的特征。
2.使用时需包括头文件#include
3.基本操作:

  • top 访问队头元素
  • empty 队列是否为空
  • size 返回队列内元素个数
  • push 插入元素到队尾 (并排序)
  • pop 弹出队头元素

4.定义:priority_queue<Type, Container, Functional>
Type 就是数据类型,Container 就是容器类型(Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list。STL里面默认用的是vector),Functional 就是比较的方式。

例:

//升序队列 priority_queue <int,vector,greater > q;

//降序队列 priority_queue <int,vector,less > q;

代码如下:

KthLargest.h

#pragma once
#include<iostream>
#include<queue>
using namespace std;
class KthLargest
{
public:
	KthLargest(int k, vector<int>& nums);
	int add(int val);
private:
	priority_queue<int, vector<int>, greater<int>>* q;
	int size;
};

KthLargest.cpp

#include "KthLargest.h"
KthLargest::KthLargest(int k, vector<int>& nums)
{
	size = k;
	q = new priority_queue<int, vector<int>, greater<int>>(size, INT_MIN);
	int i;
	for (int i = 0; i < nums.size(); i++)
	{
		add(nums[i]);
	}
}
int KthLargest::add(int val)
{
	if (val < (*q).top())
		return (*q).top();
	else
	{
		(*q).pop();
		(*q).push(val);
	}
	return (*q).top();
}

main.cpp

#include"KthLargest.h"
int main()
{
	int k = 3;
	vector<int> v;
	v.push_back(4);
	v.push_back(5);
	v.push_back(8);
	v.push_back(2);
	KthLargest* kthLargest = new KthLargest(3, v);
	cout<<(*kthLargest).add(3);   
	cout<<(*kthLargest).add(5);   
	cout<<(*kthLargest).add(10);  
	cout<<(*kthLargest).add(9);   
	cout<<(*kthLargest).add(4);
	return 0;
}

解法2:top-k算法

可以构建一个大小为k的小顶堆,且初始化为有kINT_MIN的数组。小顶堆的堆调整函数也比较常用。add函数的实现:每当加入一个数时,都与堆顶元素作比较。如果小于堆顶元素,则函数不做处理,返回堆顶元素。否则,将这个加入值替换堆顶元素,并进行小顶堆的调整,返回堆顶元素。题目的意图就是每次add函数的返回值就是此时该数据流的第k个最大的元素。

代码如下:

KthLargest.h

#pragma once
#include<iostream>
#include<vector>
using namespace std;
class KthLargest
{
public: 
	KthLargest(int k, vector<int>& nums);
	int add(int val);
	void MinHeapify(vector<int>& nums, int length, int i);
private:
	vector<int> v;
	int size;
};

KthLargest.cpp

#include "KthLargest.h"
KthLargest::KthLargest(int k, vector<int>& nums)
{
	size = k;
	for (int j = 0; j < size; j++)
		v.push_back(INT_MIN);
	for (int i = 0; i < nums.size(); i++)
		add(nums[i]);
}
int KthLargest::add(int val)
{
	if (val > v[0])
	{
		v[0] = val;
		MinHeapify(v, size, 0);
	}
	return v[0];
}
void KthLargest::MinHeapify(vector<int>& nums, int length, int i)
{
	int n_left = i * 2 + 1;  //节点i的左孩子
	int n_right = i * 2 + 2; //节点i的右孩子节点
	int min = i;  //父节点
	if (n_left < length && nums[n_left]<nums[min])
		min = n_left;
	if (n_right < length && nums[n_right]<nums[min])
		min = n_right;
	if (i != min)   //最小值不是父节点
	{
		int temp = nums[i];
		nums[i] = nums[min];
		nums[min] = temp;
		MinHeapify(nums, length, min);
	}
}

main.cpp

#include"KthLargest.h"
int main()
{
	int k=3;
	vector<int> nums;
	nums.push_back(4);
	nums.push_back(5);
	nums.push_back(8);
	nums.push_back(2);
	KthLargest m(k,nums);
	cout << m.add(3)<<endl;
	cout << m.add(5)<<endl;
	cout << m.add(10)<<endl;
	cout << m.add(9)<<endl;
	cout << m.add(4)<<endl;
	return 0;
}
发布了34 篇原创文章 · 获赞 1 · 访问量 758
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 游动-白 设计师: 上身试试

分享到微信朋友圈

×

扫一扫,手机浏览