zoukankan      html  css  js  c++  java
  • 栈和队列

    栈的基本操作

    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
  • 相关阅读:
    7-30-组队赛
    POJ 3125 Printer Queue
    7-28-比赛
    POJ 3922 A simple stone game
    POJ 1845
    第一次组队训练
    I-number
    Radar Installation
    Robots on a grid(DP+bfs())
    Dividing a Chocolate(zoj 2705)
  • 原文地址:https://www.cnblogs.com/hcl6/p/15812860.html
Copyright © 2011-2022 走看看