面试中考察栈和队列的经典算法题

💝💝💝如果你对顺序表的概念与理解还存在疑惑,欢迎观看我之前的作品👉【栈和列队详解】

上篇文章👉 【面试中顺序表常考的十大题目解析】


目录

💯前言

💯栈相关题目

⭐有效的括号

⭐逆波兰表达式求值

⭐栈的压入、弹出序列

💯队列相关题目

⭐用队列实现栈

⭐用栈实现队列

💯总结


💯前言

在技术面试中,栈和队列是数据结构领域的重要考点,经常会出现各种相关的题目来考查应聘者对这两种数据结构的理解和掌握程度。以下是一些栈和队列面试中常考的题目及解析

 

💯栈相关题目

⭐有效的括号

题目链接👉【力扣】

题目描述:给定一个只包含括号 '('')''{''}''['']' 的字符串,判断字符串中的括号是否有效。有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。

示例 1
输入:"()"
输出:true

示例 2
输入:"()[]{}"
输出:true

示例 3
输入:"(]"
输出:false

  

解题思路

我们可以使用来解决这个问题。遍历字符串中的每个字符,如果是左括号,就将其压入栈中。如果是右括号,就检查栈顶元素是否是对应的左括号,如果是,则弹出栈顶元素;如果不是,或者栈为空,则说明括号无效。最后,如果栈为空,则说明所有括号都匹配成功,字符串中的括号是有效的;否则,括号无效。

代码实现(C++)

class Solution {
public:
    bool isValid(string s) {
        stack<char> st;
        for (char c : s) {
            if (c == '(' || c == '[' || c == '{') {
                st.push(c);
            } else {
                if (st.empty()) return false;
                char top = st.top();
                if ((c == ')' && top == '(') || (c == ']' && top == '[') || (c == '}' && top == '{')) {
                    st.pop();
                } else {
                    return false;
                }
            }
        }
        return st.empty();
    }
};

⭐逆波兰表达式求值

题目链接👉【力扣】

题目描述:逆波兰表达式是一种后缀表达式,它将运算符放在操作数之后。例如,表达式 3 4 + 5 * 对应的中缀表达式是 (3 + 4) * 5。给定一个逆波兰表达式,求其求值结果。

示例
输入:["2", "1", "+", "3", "*"]
输出:9
解释:该逆波兰表达式的计算过程为:(2 + 1) * 3 = 9

解题思路

使用来解决这个问题。遍历逆波兰表达式中的每个元素,如果是数字,就将其转换为整数并压入栈中。如果是运算符,就从栈中弹出两个操作数,进行相应的运算,然后将结果压回栈中。最后,栈中剩下的唯一元素就是表达式的求值结果。

代码实现(C++)

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<int> st;
        for (string token : tokens) {
            if (token == "+" || token == "-" || token == "*" || token == "/") {
                int num2 = st.top(); st.pop();
                int num1 = st.top(); st.pop();
                if (token == "+") st.push(num1 + num2);
                else if (token == "-") st.push(num1 - num2);
                else if (token == "*") st.push(num1 * num2);
                else st.push(num1 / num2);
            } else {
                st.push(stoi(token));
            }
        }
        return st.top();
    }
};

⭐栈的压入、弹出序列

题目描述:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列 1,2,3,4,5 是某栈的压栈序列,序列 4,5,3,2,1 是该压栈序列对应的一个弹出序列,但 4,3,5,1,2 就不可能是该压栈序列的弹出序列。

解题思路

使用一个辅助栈来模拟栈的压入和弹出操作。遍历压入序列,将元素依次压入辅助栈。同时,遍历弹出序列,如果辅助栈的栈顶元素与弹出序列的当前元素相等,就将辅助栈的栈顶元素弹出,并继续比较下一个弹出元素。如果最后辅助栈为空,则说明弹出序列是可能的;否则,弹出序列是不可能的。

代码实现(C++)

class Solution {
public:
    bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {
        stack<int> st;
        int i = 0, j = 0;
        while (i < pushed.size()) {
            st.push(pushed[i++]);
            while (!st.empty() && st.top() == popped[j]) {
                st.pop();
                j++;
            }
        }
        return st.empty();
    }
};

💯队列相关题目

⭐用队列实现栈

题目链接👉

题目描述:请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作pushtoppop 和 empty

实现思路

  1. 入栈操作(push:将元素入队到一个非空队列中(如果两个队列都为空,任选一个即可)。
  2. 出栈操作(pop:将除了最后一个元素之外的所有元素从当前非空队列依次出队并入队到另一个空队列中,然后将最后一个元素出队,这个元素就是栈顶元素。
  3. 获取栈顶元素(top:与出栈操作类似,将除了最后一个元素之外的所有元素从当前非空队列依次出队并入队到另一个空队列中,然后记录最后一个元素的值(但不出队),最后再将这个元素入队回原来的队列。
  4. 判断栈是否为空(empty:检查两个队列是否都为空。

代码实现(C++)

class MyStack {
private:
    queue<int> q1;
    queue<int> q2;

public:
    void push(int x) {
        if (q1.empty()) {
            q2.push(x);
        } else {
            q1.push(x);
        }
    }

    int pop() {
        int element;
        if (q1.empty()) {
            while (q2.size() > 1) {
                q1.push(q2.front());
                q2.pop();
            }
            element = q2.front();
            q2.pop();
        } else {
            while (q1.size() > 1) {
                q2.push(q1.front());
                q1.pop();
            }
            element = q1.front();
            q1.pop();
        }
        return element;
    }

    int top() {
        int element;
        if (q1.empty()) {
            while (q2.size() > 1) {
                q1.push(q2.front());
                q2.pop();
            }
            element = q2.front();
            q1.push(element);
            q2.pop();
        } else {
            while (q1.size() > 1) {
                q2.push(q1.front());
                q1.pop();
            }
            element = q1.front();
            q2.push(element);
            q1.pop();
        }
        return element;
    }

    bool empty() {
        return q1.empty() && q2.empty();
    }
};

⭐用栈实现队列

(一)思路分析

要用栈实现队列,同样需要利用两个栈。一个栈用于入队操作(称为输入栈),另一个栈用于出队操作(称为输出栈)。当进行入队操作时,将元素直接压入输入栈。当进行出队操作时,如果输出栈为空,将输入栈中的所有元素依次弹出并压入输出栈,然后从输出栈中弹出顶部元素,这个元素就是队头元素。

(二)代码实现

  1. 结构体定义
    typedef struct {
        Stack *inputStack;
        Stack *outputStack;
    } QueueUsingStacks;

这里定义了一个结构体,包含两个指向栈的指针,用于实现队列的功能。


2. 初始化队列

    void initQueueUsingStacks(QueueUsingStacks *queue) {
        queue->inputStack = (Stack *)malloc(sizeof(Stack));
        queue->outputStack = (Stack *)malloc(sizeof(Stack));
        initStack(queue->inputStack);
        initStack(queue->outputStack);
    }

初始化时,为两个栈分配内存空间,并分别初始化它们。


3. 入队操作

    void enqueueUsingStacks(QueueUsingStacks *queue, int element) {
        pushStack(queue->inputStack, element);
    }

入队时,将元素压入输入栈


4. 出队操作

    int dequeueUsingStacks(QueueUsingStacks *queue) {
        int element;
        if (isEmptyStack(queue->outputStack)) {
            while (!isEmptyStack(queue->inputStack)) {
                pushStack(queue->outputStack, popStack(queue->inputStack));
            }
        }
        if (!isEmptyStack(queue->outputStack)) {
            element = popStack(queue->outputStack);
            return element;
        } else {
            printf("队列为空,无法出队\n");
            return -1;
        }
    }

出队时,如果输出栈为空,将输入栈中的元素转移到输出栈中,然后从输出栈中弹出顶部元素。

 

💯总结

 

通过以上对栈和队列面试常见题目的分析与解答,希望能帮助你更好地理解和掌握这两种数据结构在面试中的应用,提高你在数据结构方面的解题能力和应对面试的信心。在实际准备面试过程中,建议你多做练习,深入理解每种数据结构的特点和操作方法,以便能够灵活运用它们解决各种问题。如果你还有其他问题或需要进一步的解释,欢迎随时提问。


💝💝💝感谢你看到最后,点个赞再走吧!💝💝💝 

以下是一个投票,欢迎你参与,让我们一起了解大家对栈和队列的认知和兴趣程度: 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值