文章目录
-
- 对应力扣的题目链接
- 思路分析
- 解决方案
问题一 、239. 滑动窗口最大值
题目链接 : 239. 滑动窗口最大值 - 力扣(LeetCode)
思路分析 :
1、可能首先想到的是暴力破解 ,每一个区间,遍历一遍,找到最大值。将其搜集起来。
2、单调队列的思想 ,每次窗口移动的时候,调用que.pop(滑动窗口中移除元素的数 值),que.push(滑动窗口添加元素的数值),然后que.front()就返回我们要的最大值。
3、 当然这个队列是没有的,具体功能需要我们自己实现。
单调队列的实现( 基于一个双向队列 deque 可以对对头和队尾进行操作 )
my_push( ) 入队 :
入队之前和队列中元素进行比较,如果队列中的元素比要入队的元素小,则将其出队。
这样我们队列的对头元素总是最大值,然后我们滑动窗口移动的时候,每次都从对头拿去窗口的最大值。
void my_push( int value ){
while( !my_queue.empty() && my_queue.back() < value){
my_queue.pop_back();
}
my_queue.push_back( value );
}
// my_queue 是我们定义的一个私有成员, 他是 deque 类型
my_pop( ) 出队 :
因为我们在入队的时候,就已经将较小的元素出队了。
所以这里我们处理的是,如果窗口移除的元素value等于单调队列的出口元素,则将其出队。
//出队
void my_pop(int value){
//当我们要入队的元素和队头元素相等时,说明要丢弃的是之前队列里面的最大值
if(!my_queue_.empty() && value==myDeque_.front()){
myDeque_.pop_front() ;
}
}
视频和更详细的文字讲解(代码随想录)
代码随想录
具体解决方案:
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
myDeque myDeque_;
vector< int >data;
if( nums.size() < k ) return data;
//先放入前k个元素
for( int i = 0 ; i < k ; i++ ){
myDeque_.my_push(nums[i]);
}
//找到前k个的最大值
data.push_back( myDeque_.getMax() );
for(int i=k ; i< nums.size() ; i++ ){
myDeque_.my_pop( nums[i-k] ); //
myDeque_.my_push( nums[i] );
data.push_back( myDeque_.getMax() );
}
return data;
}
private:
class myDeque{
public:
deque< int >myDeque_; //定义一个双向队列
//出队
void my_pop(int value){
//当我们要入队的元素和队头元素相等时,说明要丢弃的是之前队列里面的最大值
if(myDeque_.empty()!=true && value==myDeque_.front()){
myDeque_.pop_front() ;
}
}
//入队
void my_push(int value){
while( myDeque_.empty()!=true && value > myDeque_.back() ){
myDeque_.pop_back();
}
myDeque_.push_back(value);
}
int getMax(){
return myDeque_.front();
}
};
};
问题二 、347.前 K 个高频元素
题目链接:
347. 前 K 个高频元素 - 力扣(LeetCode)
思路分析:
- 遇到一个数出现的次数,我们首先想到 使用map 这个容器,key 记录要计算的数,value 出现的次数
- 优先级队列(底层是实现是一个堆),将map中的数据进行排序,采用小顶堆
- 最后反向输入到需要返回的数组中
视频和更详细的文字讲解(代码随想录):
代码随想录
解决方案:
class Solution {
public:
//自定义比较函数
class MyCompare{
public:
bool operator()(const pair<int ,int>&left , const pair<int ,int>&right){
return left.second > right.second;
}
};
vector<int> topKFrequent(vector<int>& nums, int k) {
// if(nums.size() < k ) return ret;
unordered_map< int ,int >temp;
// key 是数字, value是出现的次数
for(int i=0 ; i<nums.size() ; i++){
temp[ nums[i] ]++;
}
// 排序使用 ,小顶堆(优先级队列)
priority_queue<pair<int, int>, vector<pair<int, int>>, MyCompare > pq;
//将map中的数据放入优先级队列,并从小到大排序
for(unordered_map<int,int>::iterator it = temp.begin() ; it!=temp.end() ; it++){
pq.push(*it);
if(pq.size() >k ){
pq.pop(); //将最小的值出队
}
//入队,并排序
}
//将队列中的数据导入ret
vector<int>ret(k);
for( int i=k-1 ; i>=0 ;i-- ){
ret[i]=pq.top().first;
pq.pop();
}
return ret;
}
};