栈队列相关面试算法总结

栈队列相关面试算法总结

栈和队列虽然是特点针锋相对的两个数据结构,但他们之间亦有密切的联系,比如“用两个栈实现队列”,“用两个队列实现栈”。

栈相关面试算法

利用栈的特性先进后出(FILO)去解决问题,主要用以下特性:

  1. 数据是线性的;
  2. 问题中常常涉及到数据的来回比较;比如每日温度、括号比配、字符串解码、去掉重读字母等问题;
  3. 问题中涉及到数据的转置,例如进制问题,链表倒序打印问题;

1. LeetCode 20 : 有效的括号

LeetCode20

/*
 * 1
 * LeetCode 20 : 有效的括号
 * https://leetcode-cn.com/problems/valid-parentheses/
 */
bool isValid(string s)
{
    stack<char> rec;
    for(int i = 0; i < s.size(); i++) {
        if(s[i] == '(' || s[i] == '{' || s[i] == '[') {
            rec.push(s[i]);
        } else {
            if(rec.empty()) {
                return false;
            }
            char c = rec.top();
            rec.pop();
            char match;
            if(s[i] == ')') {
                match = '(';
            } else if(s[i] == '}') {
                match = '{';
            } else {
                match = '[';
            }
            if(match != c) {
                return false;
            }
        }
    }
    if(!rec.empty()) {
        return false;
    }
    return true;
}

2. LeetCode 844 : 比较含退格的字符串

LeetCode844

/*
 * 2
 * LeetCode 844 : 比较含退格的字符串
 * https://leetcode-cn.com/problems/backspace-string-compare/
 */
void helper(string& s, stack<char>& res)
{
    for(int i = 0; i < s.size(); i++)
    {
        if(s[i] != '#')
        {
            res.push(s[i]);
        }
        else if(!res.empty())
        {
            res.pop();
        }
    }
}
bool backspaceCompare(string S, string T)
{
    stack<char> s,t;
    helper(S,s);
    helper(T,t);
    if(s.size() != t.size())
    {
        return false;
    }
    while(!t.empty())
    {
        if(s.top() != t.top())
        {
            return false;
        }
        s.pop();
        t.pop();
    }
    return true;
}

3. LeetCode 144 : 二叉树的前序遍历

LeetCode144

/*
 * 3
 * LeetCode 144 : 二叉树的前序遍历
 * https://leetcode-cn.com/problems/binary-tree-preorder-traversal/
 */
vector<int> preorderTraversal(TreeNode* root)
{
    vector<int> res;
    if(root == NULL)
        return res;
    stack<TreeNode*> sta;
    sta.push(root);
    while(!sta.empty())
    {
        TreeNode* node = sta.top();
        sta.pop();
        res.push_back(node->val);

        if(node->right)
            sta.push(node->right);
        if(node->left)
            sta.push(node->left);
    }
    return res;
}

4. LeetCode 94 : 二叉树的中序遍历

LeetCode94

/*
 * 4
 * LeetCode 94 : 二叉树的中序遍历
 * https://leetcode-cn.com/problems/binary-tree-inorder-traversal/
 */
vector<int> inorderTraversal(TreeNode* root)
{
    vector<int> res;
    if(root == NULL)
        return res;
    stack<TreeNode*> sta;
    TreeNode* node = root;
    while(!sta.empty() || node != NULL) {
        while(node != NULL) {
            sta.push(node);
            node = node->left;
        }
        if(!sta.empty()) {
            node = sta.top();
            sta.pop();
            res.push_back(node->val);
            node = node->right;
        }
    }
    return res;
}

5. LeetCode 150 : 逆波兰表达式求值

LeetCode150

/*
 * 5
 * LeetCode 150 : 逆波兰表达式求值
 * https://leetcode-cn.com/problems/evaluate-reverse-polish-notation/
 */

int evalRPN(vector<string>& tokens)
{
    stack<int> stack;
    int size = tokens.size();
    for(int i = 0;i<size;i++) {
        string str = tokens[i];
        int first;
        int second;
        if(str=="+") {
            second = stack.top();stack.pop();
            first = stack.top();stack.pop();
            stack.push(second+first);
        } else if(str=="-") {
            second = stack.top();stack.pop();
            first = stack.top();stack.pop();
            stack.push(first-second);
        } else if(str=="*") {
            second = stack.top();stack.pop();
            first = stack.top();stack.pop();
            stack.push(first*second);
        } else if(str=="/") {
            second = stack.top();stack.pop();
            first = stack.top();stack.pop();
            stack.push(first/second);
        } else {//为整数,解析并压栈
            int val = atoi(str.c_str());
            stack.push(val);
        }
    }
    return stack.top();
}

6. LeetCode 155 : 最小栈

LeetCode155

/*
 * 6
 * LeetCode 155 : 最小栈
 * https://leetcode-cn.com/problems/min-stack/
 */
class MinStack
{
/*
在入栈时,如果这个元素比最小值小,那么,我们让最小值入栈,然后将元素值赋给最小值,即新的最小值,
然后正常将这个元素入栈;在出栈时,如果栈顶元素与最小值相等,说明他的下一个元素是之前push的最小值(上一个),
出栈后,将这个之前的最小值赋值给最新的最小值。(每次push进去的最小值都是下面元素的最小值)
*/
public:
    /** initialize your data structure here. */
    stack<int> s;
    int min;
    void push(int x) {
        if(s.empty()) {
            s.push(x);
            min = x;
        } else {
            if(x <= min) {
                s.push(min);
                min = x;
            }
            s.push(x);
        }
    }
    void pop() {
        if(s.empty())
            return ;
        int p = s.top();
        s.pop();
        if(!s.empty() && p == min)
        {
            min = s.top();
            s.pop();
        }
    }

    int top() {
        return s.top();
    }

    int getMin() {
        return min;
    }
};

7. LeetCode 225 : 用队列实现栈

LeetCode225

/*
 * 7
 * LeetCode 225 : 用队列实现栈
 * https://leetcode-cn.com/problems/implement-stack-using-queues/
 */
class MyStack
{
public:
    queue<int> q;
public:
    /** Initialize your data structure here. */
    MyStack()
    {
    }

    /** Push element x onto stack. */
    void push(int x) {
        int n = q.size();
        q.push(x);
        while(n > 0) {
            q.push(q.front());
            q.pop();
            n--;
        }
    }

    /** Removes the element on top of the stack and returns that element. */
    int pop() {
        int n = q.front();
        q.pop();
        return n;
    }

    /** Get the top element. */
    int top() {
        return q.front();
    }

    /** Returns whether the stack is empty. */
    bool empty() {
        if(q.empty())
            return true;
        return false;
    }
};
/**
 * Your MyStack object will be instantiated and called as such:
 * MyStack* obj = new MyStack();
 * obj->push(x);
 * int param_2 = obj->pop();
 * int param_3 = obj->top();
 * bool param_4 = obj->empty();
 */

8. LeetCode 224 : 基本计算器

LeetCode224

/*
 * 8
 * LeetCode 224 : 基本计算器
 * https://leetcode-cn.com/problems/basic-calculator/
 */
int calculate(string s)
{
    int res = 0, sign = 1, n = s.size();
    if(n == 0)
        return 0;
    stack<int> st;
    for(int i = 0; i < n; i++)
    {
        if(s[i] >= '0') {
            int num = 0;
            while(i < n && s[i] >= '0')
            {
                num = num*10 + s[i++] - '0';
            }
            res += sign*num;
            i--;
        } else if(s[i] == '+') {
            sign=1;
        } else if(s[i] == '-') {
            sign=-1;
        } else if(s[i] == '(') {
            st.push(res);
            st.push(sign);
            res = 0;
            sign = 1;
        } else if(s[i] == ')') {
            res *= st.top(); st.pop();
            res += st.top(); st.pop();
        }
    }
    return res;
}

队列相关面试算法

1. 剑指 Offer 59 - I : 滑动窗口的最大值

剑指Offer59-1

// 队列 queue
/*
 * 1
 * 剑指 Offer 59 - I : 滑动窗口的最大值
 * https://leetcode-cn.com/problems/hua-dong-chuang-kou-de-zui-da-zhi-lcof/
 */
/*
deque : 双端队列
// 在队头插入元素 n
void push_front(int n);
// 在队尾插入元素 n
void push_back(int n);
// 在队头删除元素
void pop_front();
// 在队尾删除元素
void pop_back();
// 返回队头元素
int front();
// 返回队尾元素
int back();
*/
vector<int> maxSlidingWindow(vector<int>& nums, int k)
{
    // 单调队列,从队头到队尾递减
    vector<int> ans;
    deque<int> deq;
    for(int i = 0; i < nums.size(); i++)
    {
        while(!deq.empty() && nums[deq.back()] <= nums[i]){
            deq.pop_back();
        }
        while(!deq.empty() && (deq.front() < i-k+1)) {
            //if判断条件中的第二个是为了判断队头是否过期,也就是说队头的索引是否小于当前索引
            deq.pop_front();
        }
        deq.push_back(i);
        if(i >= k-1)
            ans.push_back(nums[deq.front()]);
    }
    return ans;
}

以上是栈和队列的相关面试算法题目汇总,个别题目也给出了解题思路和注释。
所有代码都可以去我的GitHub网站查看,后续也将继续补充其他数据结构的相关面试算法题目。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值