栈和队列

栈的基本操作

empty() 堆栈为空则返回真

pop() 移除栈顶元素 (删除)

push() 在栈顶增加元素 (增加)

size() 返回栈中元素数目

top() 返回栈顶元素,不删除(获取)

队列的基本操作

back()返回最后一个元素

empty()如果队列空则返回真

front()返回第一个元素

pop()删除第一个元素

push()在末尾加入一个元素

size()返回队列中元素的个数

 

232. 用栈实现队列 - 力扣(LeetCode) (leetcode-cn.com)

注意细节,要等输出栈空了才能转移输入栈元素到输出栈,否则先push1234,再pop一次,输出还剩下234,再push5,这时候如果直接放入输出栈,会直接放在头部,首先输出,再依次输出的话就是5234了

 1 class MyQueue {
 2 public:
 3     stack<int> stIn;
 4     stack<int> stOut;
 5     MyQueue() {
 6 
 7     }
 8 
 9     void push(int x) {//push和pop交替,那么这种情况,必须stOut为空了,再转移stIn里的数据
10         stIn.push(x);
11     }
12     
13     int pop() {
14        
15         int res = this->peek();
16         stOut.pop();
17         return res;
18     }
19     
20     int peek() {
21         if(stOut.empty())
22             while(!stIn.empty()){
23                 stOut.push(stIn.top());
24                 stIn.pop();
25             }
26         int res = stOut.top();
27         return res;
28     }
29     
30     bool empty() {
31         return stIn.empty()&&stOut.empty();
32     }
33 };
View Code

 

225. 用队列实现栈 - 力扣(LeetCode) (leetcode-cn.com)

class MyStack {
public:
    queue<int> que;
    MyStack() {

    }
    
    void push(int x) {
        que.push(x);
    }
    
    int pop() {
        int res = que.back();
        int size = que.size();
        size--;
        while(size--){
            que.push(que.front());
            que.pop();
        }
        que.pop();
        return res;
     
    }
    
    int top() {
        return que.back();
    }
    
    bool empty() {
        return que.empty();
    }
};
View Code

 

20. 有效的括号 - 力扣(LeetCode) (leetcode-cn.com)

 1 class Solution {
 2 public:
 3     bool isValid(string s) {
 4         stack<char> st;
 5         for(int i=0;i<s.size();i++){
 6             if(s[i]=='('||s[i]=='{'||s[i]=='[')
 7                 st.push(s[i]);
 8             else{
 9                 if(st.empty())//")))"
10                     return false;
11                 char temp = st.top();
12                 st.pop();
13                 cout<<s[i]<<temp;
14                 if((temp=='('&&s[i]==')')||(temp=='{'&&s[i]=='}')||(temp=='['&&s[i]==']'))//三种正确情况,就继续执行
15                     continue;
16                 else    
17                     return false;
18             }
19         }
20         if(st.empty())
21             return true;
22         else   
23             return false;
24     }
25 };
View Code

 另外一种巧写法,比如碰到左括号就放入对应右括号哈哈哈,这样就可以直接判等了

 1 class Solution {
 2 public:
 3     bool isValid(string s) {
 4         stack<char> st;
 5         for(int i=0;i<s.size();i++){
 6             if(s[i]=='(')
 7                 st.push(')');
 8             else if(s[i]=='{')
 9                 st.push('}');
10             else if(s[i]=='[')
11                 st.push(']');
12             else if(st.empty()||st.top()!=s[i])
13                 return false;
14             else
15                 st.pop();
16         }
17         return st.empty();
18     }
19 };
View Code

 

150. 逆波兰表达式求值 - 力扣(LeetCode) (leetcode-cn.com)

 1 class Solution {
 2 public:
 3     int evalRPN(vector<string>& tokens) {
 4         stack<int> st;
 5         for(int i=0;i<tokens.size();i++){
 6             if(tokens[i]=="+"|tokens[i]=="-"||tokens[i]=="*"||tokens[i]=="/"){//碰到运算符就弹两个数出来操作,操作完压栈,碰到数字压栈
 7                 int a = st.top();st.pop();//注意a,b顺序,a先出是靠后的数,b在a前
 8                 int b = st.top();st.pop();
 9                 if(tokens[i]=="+")
10                     st.push(b+a);
11                 else if(tokens[i]=="-")
12                     st.push(b-a);
13                 else if(tokens[i]=="*")
14                     st.push(b*a);
15                 else if(tokens[i]=="/")
16                     st.push(b/a);
17             }else{
18  
19                 st.push(stoi(tokens[i]));
20             }
21         }
22         return st.top();
23     }
24 };
View Code

 

滑动窗口k,维护的队列长度其实是<=k的,因为队列进行了数据筛选,如果数组下标大的还比下标小的数据大,那么下标小的数在队列(滑动窗口)里就没有存在的必要了,基于这种情况做出的单调性

比如 1,3,-1,-3,5,3,6,7,k=3

初始化队列:3,-1

i=3:3,-1,-3

i=4:5

i=5:5,3

i=6:6

i=7:7

懂了吧哈哈哈

239. 滑动窗口最大值 - 力扣(LeetCode) (leetcode-cn.com)

 1 class Solution {
 2 private:
 3     class MyQueue{
 4     public:
 5         deque<int> que;
 6         void pop(int value){
 7             if(!que.empty()&&value == que.front())//value和front大小关系,value不可能闭front大,
 8             //如果比front小,那么队列里没有value这个值了,因为递增,value早在front加入队列时push操作那就被移除了,这时候就不用移除了
 9                 que.pop_front();
10 
11         }
12         void push(int value){
13             while(!que.empty()&&value>que.back()){//比它后放入队列,也就是在队列靠后位置还比队列前面的数大,那就前面的数没有存在的必要了
14                 que.pop_back();
15             }
16             que.push_back(value);
17         }
18         int front(){
19             return que.front();
20         }
21     };
22 public:
23     vector<int> maxSlidingWindow(vector<int>& nums, int k) {
24         MyQueue que;
25          vector<int> result;
26         for(int i=0;i<k;i++){
27            que.push(nums[i]);
28         }
29         result.push_back(que.front());//这里要先放入一次结果
30         for(int i=k;i<nums.size();i++){
31             que.pop(nums[i-k]);
32             que.push(nums[i]);
33             result.push_back(que.front());
34         }
35         return result;
36     }
37 };
View Code

 

自定义重载优先队列,第一种pair实现,第一种结构体,最后一种就是契合默认优先队列,按第一位排序且是大根堆,队首最大

自定义vector,第四种,时间慢了,维护了n个元素,nlog(n),队列的话只维护k个元素,就是nlog(k)

347. 前 K 个高频元素 - 力扣(LeetCode) (leetcode-cn.com)

这个题也可以不用重载,放入优先队列时,交换一下first和second的位置,因为是根据second来排序,所以把second排在第一位,然后有因为默认是大根堆每次弹出最大的,取相反数就刚好了。还要注意结果数据和队列一次弹出数据是反着的。

如果是设置成友元函数(friend),一定要注意: 
(1)当重载友元函数时,将没有隐含的参数this指针。这样,对双目运算符,友元函数有2个参数,对单目运算符,友元函数有一个参数。 
(2)有些运行符不能重载为友元函数,它们是:=,(),[]和->。 

比如这道题结构体重载<,就要用friend消除this指针,不然报错三个参数啥的。

 1 class Solution {
 2 public:
 3     typedef pair<int, int> PII;
 4     struct cmp{
 5         bool operator ()(const PII& l,const PII& r){
 6            return l.second>r.second;
 7         }
 8     };
 9        
10     vector<int> topKFrequent(vector<int>& nums, int k) {
11         
12         unordered_map<int, int> mp;
13         for(auto num: nums)  mp[num] ++ ;
14         priority_queue<PII,vector<PII>,cmp> pq;
15         for(auto item: mp){
16             pq.push(item);
17             if(pq.size() > k) pq.pop();
18         }
19         vector<int> res(k);
20         for(int i = k - 1; i >= 0; i --){
21             res[i] = pq.top().first;
22             pq.pop();
23         }
24         return res;
25     }
26 };
View Code
 1 class Solution {
 2 public:
 3     struct node{
 4         int x, y;
 5         friend bool operator < (node a, node b){
 6             return a.y > b.y;                               //y小的优先
 7         }
 8     };
 9        
10     vector<int> topKFrequent(vector<int>& nums, int k) {
11         unordered_map<int, int> mp;
12         for(auto num: nums)  mp[num] ++ ;
13         priority_queue<node> pq;
14         for(auto item: mp){
15             node t;
16             t.x = item.first;
17             t.y = item.second;
18             pq.push(t);
19             if(pq.size() > k) pq.pop();
20         }
21         vector<int> res(k);
22         for(int i = k - 1; i >= 0; i --){
23             res[i] = pq.top().x;
24             pq.pop();
25         }
26         return res;
27     }
28 };
View Code
 1 class Solution {
 2 public:
 3     vector<int> topKFrequent(vector<int>& nums, int k) {
 4         typedef pair<int, int> PII;
 5         unordered_map<int, int> mp;
 6         for(auto num: nums)  mp[num] ++ ;
 7         priority_queue<PII> pq;
 8         for(auto item: mp){
 9             PII t(-item.second, item.first);
10             pq.push(t);
11             if(pq.size() > k) pq.pop();
12         }
13         vector<int> res(k);
14         for(int i = k - 1; i >= 0; i --){
15             res[i] = pq.top().second;
16             pq.pop();
17         }
18         return res;
19     }
20 };
View Code
 1 class Solution {
 2 public:
 3     struct node{
 4         int x, y;
 5         friend bool operator < (node a, node b){
 6             return a.y > b.y;                               //y小的优先
 7         }
 8     };
 9        
10     vector<int> topKFrequent(vector<int>& nums, int k) {
11         unordered_map<int, int> mp;
12         for(auto num: nums)  mp[num] ++ ;
13         vector<node> pq;
14         for(auto item: mp){
15             node t;
16             t.x = item.first;
17             t.y = item.second;
18             pq.push_back(t);
19         }
20         sort(pq.begin(),pq.end());
21         vector<int> res(k);
22         for(int i = 0; i < k; i ++){
23             res[i] = pq[i].x;
24         }
25         return res;
26     }
27 };
View Code

 

42. 接雨水 - 力扣(LeetCode) (leetcode-cn.com)

 1 class Solution {//记录当前列最左边高度和最右边高度,取他们之间较小的那个,与当前列高度作差就是当前列的雨水
 2 public://第一和最后不接水
 3     int trap(vector<int>& height) {//化整为零,不要想着一次性求解每一步大块面积,一数列一数列随着i的遍历来。不要一会按行计算一会按列计算,稀里糊涂。一直按行计算也行。
 4         int sum = 0;
 5         vector<int>left(height.size(),height[0]);vector<int>right(height.size(),height[height.size()-1]);
 6         for(int i=1;i<height.size()-1;i++){
 7             left[i] = max(left[i-1],height[i]);
 8         }
 9         for(int i=height.size()-2;i>=0;i--){
10             right[i] = max(right[i+1],height[i]);
11         }
12         for(int i=1;i<height.size()-1;i++){
13             sum+=max(0,min(left[i],right[i])-height[i]);
14         }
15         return sum;
16 
17     }
18 };
View Code

 

posted @ 2022-01-17 11:52  剩下的交给时间就好  阅读(28)  评论(0编辑  收藏  举报