程序员代码面试指南 第一章 栈与队列

1.1设计一个有getMin功能的栈(LC155)

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

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack obj = new MinStack();
 * obj.push(x);
 * obj.pop();
 * int param_3 = obj.top();
 * int param_4 = obj.getMin();
 */

1.2 由两个栈组成的队列(LC232)

class MyQueue {
public:
    /** Initialize your data structure here. */
    MyQueue() {
        
    }
    
    /** Push element x to the back of queue. */
    void push(int x) {
       s1.push(x); 
    }
    
    /** Removes the element from in front of queue and returns that element. */
    int pop() {
        if(s2.empty()){
            while(!s1.empty()){
                s2.push(s1.top());
                s1.pop();
            }          
        }
        int res=s2.top();
        s2.pop();
        return res;
    }
    
    /** Get the front element. */
    int peek() {
        if(s2.empty()){
            while(!s1.empty()){
                s2.push(s1.top());
                s1.pop();
            }          
        }
        int res=s2.top();
        return res;
    }
    
    /** Returns whether the queue is empty. */
    bool empty() {
        return s1.empty()&&s2.empty();
    }
private:
    stack<int> s1,s2;
};

/**
 * Your MyQueue object will be instantiated and called as such:
 * MyQueue obj = new MyQueue();
 * obj.push(x);
 * int param_2 = obj.pop();
 * int param_3 = obj.peek();
 * bool param_4 = obj.empty();
 */

1.3 仅用递归函数和栈操作逆序一个栈

思路:设栈的元素数目为n,当n等于2时,将栈底元素取出然后入栈;当n=3时,将栈底元素取出,问题转化为n=2的逆序问题,执行完毕后再将取出的元素入栈。利用递归来求解,函数一:将栈底的元素返回并移除;函数二:逆序一个栈。

 

1.4 猫狗队列

1.5 用一个栈实现另一个栈的排序

思路:将要排序的栈记为stack,申请的辅助栈记为help。在stack上执行pop操作,弹出的元素记为cur。如果cur小于或等于help的栈顶元素,则将cur直接压入help。如果cur大于help的栈顶元素,则将help的元素逐一弹出压入stack,直到cur小于或等于help的栈顶元素,再将cur压入help。一直执行以上步骤,直到stack中的元素全部压入help。最后将help中的元素逐一压入stack,即完成排序。

1.6 用栈来求解汉诺塔问题

1.7生成窗口的最大值数组(LC239)

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        vector<int> res;
        if(nums.size()==0||k<1||nums.size()<k)
            return res;
        deque<int> dq;
        for(int i=0;i<nums.size();i++){
            while(!dq.empty()&&nums[dq.back()]<=nums[i])dq.pop_back(); //nums注意不要写错
            dq.push_back(i);
            if(dq.front()+k==i)dq.pop_front();
            if(i>=k-1)res.push_back(nums[dq.front()]);
        }
        return res;
    }
};

1.8 构造数组的MaxTree

思路:遍历这个数组,找到每一个数左边第一个最大的和右边第一个最大的,选择它们两个中较小的那个数。如果左边或右边没有,那么就选择有的那个,如果都没有则这个数肯定是最大的数。选择出来的数,我们把它当做该数的父节点。以这样的方式构造该树。

证明:数组中的数都不同,一个较小数一定会以一个比他大的数为父节点,每个数字往上找,肯定能找到一个最大值。所以它满足只构造出来了一棵树而不是两棵树。那么这棵树为什么是二叉树呢?试想下,如果节点Node的左子树有2个子节点,记为k1、k2,不妨设k1<k2<Node。根据我们的规则,我们在左右两边各取第一个比它大的数,在左边/右边中选一个较小的当做其父节点,那么k1。所以必定可以推出k1与k2父节点不可能同时为Node。所以构造的树是一棵二叉树。

用栈维护一个单调递减序列,从左到右遍历每一个数,当栈顶元素小于当前数,进行pop操作直到栈顶元素大于当前数或者栈为空,此时可以得到当前元素左边第一个比它大的数;同理,可得每个数右边的第一个比它大的数。
 

1.9求最大子矩阵的大小(LC85)

class Solution {
public:
    int maximalRectangle(vector<vector<char>>& matrix) {
        if(matrix.size()==0||matrix[0].size()==0)return 0;
        int m=matrix.size();
        int n=matrix[0].size();
        vector<int> heights(n,0);
        int res=0;
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(matrix[i][j]=='1')heights[j]++;
                else heights[j]=0;
            }
            res=max(res,largestRectangleArea(heights));
        }
        return res;
    }

    int largestRectangleArea(vector<int>& heights) {
        //if(heights.size()==0)return 0;
        stack<int> s;
        int res=0;
        for(int i=0;i<heights.size();i++){
            while(!s.empty()&&heights[i]<=heights[s.top()]){
                int j=s.top();
                s.pop();
                int k=s.empty()?-1:s.top();
                res=max(res,heights[j]*(i-k-1));
            }
            s.push(i);           
        }
        while(!s.empty()){
                int j=s.top();
                s.pop();
                int k=s.empty()?-1:s.top();
                res=max(res,(int)(heights[j]*(heights.size()-k-1)));
            }
        return res;
    }
};

1.10 最大值减去最小值小于或等于num的子数组数量

点赞