剑指offer09.用两个栈实现队列 30.包含min函数的栈(两个栈)59-I 滑动窗口的最大值(优先队列大顶堆) 59-II 队列的最大值(队列+头指针尾指针)

 ![在这里插入图片描述](https://img-blog.csdnimg.cn/8864dfb4215141b0912954597a19364f.png)

思路:因为队列是先进先出 而栈是先进后出,需要另外一个栈作辅助
append就直接append进栈里,delete先判断当前栈stk1是否为空,空就return-1,不为空就返回栈底元素(因为队列是先进先出
但栈底无法直接返回,因为要一个一个放到stk2里,这样stack2的top()就是stk1的栈底,然后再把stk1的元素从stk2一个一个再放回stk1

class CQueue {
public:
    stack<int> stk1;
    stack<int> stk2;
    CQueue() {}
    
    void appendTail(int value) {
        stk1.push(value);

    }
    
    int deleteHead() {
        int result;
        if(stk1.empty()) return -1;//如果栈为空,表示当前栈元素为空
        else
        {
            while(!stk1.empty())
            {
                int cur=stk1.top();
                stk1.pop();
                stk2.push(cur);
            }//stk1的元素倒到stk2里
            result=stk2.top();
            stk2.pop();
            while(!stk2.empty())
            {
                int cur=stk2.top();
                stk2.pop();
                stk1.push(cur);
            }

            
        }
        return result;

    }

};

剑指offer09.用两个栈实现队列 30.包含min函数的栈(两个栈)59-I 滑动窗口的最大值(优先队列大顶堆) 59-II 队列的最大值(队列+头指针尾指针)_第1张图片
思路:一个正常栈,一个辅助栈(存比当前辅助站顶部元素小的元素)
1.push的话,正常栈就直接push,对于辅助栈,如果栈空或者当前push的x比栈顶元素小,push进辅助栈
2.这样调.min()函数,直接return 辅助栈.top()
3.调top()函数,return 正常栈.top()
4…pop的话,都要pop正常栈的栈顶,但辅助站需不需要pop就要看正常栈和辅助栈的栈顶元素是否相同,如果相同,辅助栈也要pop,不然我正常栈-3已经pop了,辅助栈不pop,那么找min,还是return的辅助栈的-3.

class MinStack {
public:
    /** initialize your data structure here. */
    stack<int> stk;
    stack<int> stk_min;
    MinStack() {}
    
    void push(int x) {
     stk.push(x);
     if(stk_min.empty()||x<=stk_min.top()) stk_min.push(x);
    }
    
    void pop() {
    if(stk.top()==stk_min.top())
    {
        stk_min.pop();
    }
    stk.pop();
    }
    
    int top() {
    return stk.top();
    }
    
    int min() {
        return stk_min.top();
    }
};

剑指offer09.用两个栈实现队列 30.包含min函数的栈(两个栈)59-I 滑动窗口的最大值(优先队列大顶堆) 59-II 队列的最大值(队列+头指针尾指针)_第2张图片
最开始的思路很简单,每一个窗口里遍历找最大值,然后存进result,返回
当时心想:这也能算难题,我两分钟ak,然后哈哈哈超时超时超时

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        int left=0,max=0;
        vector<int> subnums;
        vector<int> maxnums;
        int min=*min_element(nums.begin(),nums.end());
        while(left+k<=nums.size())
        {
            max=min;
            for(int i=left;i<left+k;i++)
            {
                //subnums.push_back(nums[i]);
                max=max>nums[i]?max:nums[i];
            }
            maxnums.push_back(max);
            left++;
        }
        return maxnums;
    }
};

应该是查找的时候太慢了,查找复杂度为n,整体复杂度n平方
使用优先队列 时间复杂度(logn) 空间复杂度n

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k)
    {
     priority_queue<pair<int,int> > q;
     vector<int> result;
     int len=nums.size();
     for(int i=0;i<k;i++)
     {
         q.emplace(nums[i],i);//第一个滑动窗口
     }
     //q.top().first是对应的nums[i],q.top().second对应的是i
     result.push_back(q.top().first);//第一个滑动窗口的最大值
     for(int i=k;i<len;i++)//往后面一个元素一个元素滑动扩大
     {
         q.emplace(nums[i],i);
 //如果最大的元素在滑动窗口的左侧,pop()
         while(q.top().second<=i-k)
         {
          q.pop();
         }
         result.push_back(q.top().first);
     }
     return result;
    }
};

剑指offer09.用两个栈实现队列 30.包含min函数的栈(两个栈)59-I 滑动窗口的最大值(优先队列大顶堆) 59-II 队列的最大值(队列+头指针尾指针)_第3张图片
自己在类里面定义一个q[20000],头指针begin=0,尾指针end=0
push q[end++]=value,队尾加入元素
pop 先判断队列是否为空(begin==end)不为空直接return q[begin++]
max():遍历从头begin遍历到尾巴end找最大值return

class MaxQueue {
    int q[20000];
    int begin=0,end=0;
public:

    MaxQueue() {}
    
    int max_value() {
        int max=-1;
        for(int i=begin;i<end;i++)
        {
            max=max>q[i]?max:q[i];
        }
        return max;
    }
    
    void push_back(int value) {
        q[end++]=value;

    }
    
    int pop_front() {
        if(begin==end) return -1;
        return q[begin++];
    }
    
};

你可能感兴趣的:(算法)