刚考完试,休息了一天,一天写两天的东西,好累
Leetcode 239 滑动窗口最大值
题目链接 239 滑动窗口最大值
本题目其实用暴力的方法还是比较好想的,但是由于有限定时间,所以就可以用数据结构——队列,因为我们要取到最大值,所以我们要用单调队列:
这个题目难想的点就是怎么维护最大值:我们要维护最大值就要将最大值放到队列的出口,这样我们方便取最大值,既然要放到队列出口,我们就要保证队列中的元素单调递减才行,所以这里运用到了单调队列,最关键的两点:第一,我们需要在对队列输入元素时,将即将要进入的元素和前面的元素做对比,如果比前面的元素大就需要将前面的元素一个一个弹出,反之就不弹出,就直接将该元素直接输入队列中,第二就是在滑动到下一个区间时,如果最大值(队列front的值)如果和即将脱离区间的元素一样的话,就要将队列中的front元素弹出,重新第一步的操作,还要强调一点,需要将最大值都用vector储存一下。
整体就是这个思路,下面就是上代码:
class Solution {
private:
class MyQueue{
public:
deque<int> que;
//与即将脱离窗口区间的值相等就弹出//更新区间元素
void pop(int val){
if(!que.empty()&&val == que.front()){
que.pop_front();
}
}
//输入元素,并且我们原则是保留尽可能大的值,按照单调递减排序
// 如果push的数值大于入口元素的数值,那么就将队列后端的数值弹出,直到push的数值小于等于队列入口元素的数值为止。
void push(int val){
while(!que.empty()&&val > que.back()){
que.pop_back();
}
que.push_back(val);
}
//取最大值,保留最大值
int front(){
return que.front();
}
};
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
MyQueue que;//调用
vector<int> result;//定义数组储存最大值
for(int i=0;i<k;i++){//先把区间内的第一批元素输入
que.push(nums[i]);
}
result.push_back(que.front());//去最大值
for(int i=k;i<nums.size();i++){//不停的更新区间
que.pop(nums[i-k]);//弹出元素 滑动窗口移除最前面元素
que.push(nums[i]);//输入元素 滑动窗口前加入最后面的元素
result.push_back(que.front());//取最大值
}
return result;
}
};
Leetcode 347. 前 K 个高频元素
题目链接 347 前 K 个高频元素
本题目可以用的方法有很多,其实最简单的就是sort排序,可是时间复杂度不合适,我们学习一种新的方法,优先级队列,首先优先级队列对外接口只是从队头取元素,从队尾添加元素,再无其他取元素的方式,看起来就是一个队列。而且优先级队列内部元素是自动依照元素的权值排列。在缺省状态下(即系统默认状态)priority_queue利用max-heap(大顶堆)完成对元素的排序,这个大顶堆是以vector为表现形式的complete binary tree(完全二叉树)。堆是一棵完全二叉树,树中每个结点的值都不小于(或不大于)其左右孩子的值。 如果父亲结点是大于等于左右孩子就是大顶堆,小于等于左右孩子就是小顶堆。在这之前,我们需要统计元素出现的频率,这一类的问题可以使用map来进行统计。(前面讲过哈希中的map),然后对频率进行排序就用优先级队列,还有一个问题就是是用大顶堆还是小顶堆,假设我们用大顶堆(二叉树结构)我们每次更新时,都把树根弹出去(即最高),所以留下的都是小元素,所以我们要用小顶堆来解决这个问题:
class Solution {
public:
class mycomparison{
public:
//这里就是小顶堆
bool operator()(const pair<int,int>& lhs,const pair<int,int>& rhs ){//定义在优先队列中的排序函数
return lhs.second > rhs.second;
}
};
vector<int> topKFrequent(vector<int>& nums, int k) {
//运用map对元素出现频率进行一个统计
unordered_map<int,int> map;
for(int i=0;i<nums.size();i++){
map[nums[i]]++;
}
//定义优先队列(利用小顶堆)
priority_queue<pair<int,int>,vector<pair<int,int>>,mycomparison> pri_que;
for(unordered_map<int,int>::iterator it = map.begin();it!=map.end();it++){//对map中的所有元素进行遍历
pri_que.push(*it);//对优先队列进行输入元素
if(pri_que.size()>k){//如果大于k的部分,就弹出范围内中的最小值
pri_que.pop();
}
}
//倒序回来,存储到result中
vector<int> result(k);
for(int i=k-1;i>=0;i--){
result[i] = pri_que.top().first;
pri_que.pop();//删除队列开头元素,释放内存
}
return result;
}
};
end