面试题系列3(数据结构)——栈

面试题1

题目

改变元素的序列

1. 若进栈序列为 1,2,3,4 ,进栈过程中可以出栈,则下列不可能的一个出栈序列是()

A: 1,4,3,2

B: 2,3,4,1

C: 3,1,4,2

D: 3,4,2,1

答案:C

2.一个栈的初始状态为空。现将元素1、2、3、4、5、A、B、C、D、E依次入栈,然后再依次出栈,则元素出栈的顺

序是( )。

A: 12345ABCDE

B: EDCBA54321

C: ABCDE12345

D: 54321EDCBA

答案:B


面试题2

题目

将递归转化为循环 如:逆序打印链表

1.递归

public void display2(Node pHead){
    if (pHead == null){
        return;
    }
    if(pHead.next == null){
        System.out.print(pHead.val+" ");
        return;}
    display2(pHead.next);
    System.out.print(pHead.val+" ");
}

图解:

2.循环的方式:使用栈,先进后出

public void display3(Node pHead){
    Stack<Node> stack = new Stack<>();
    Node cur = head;
    while (cur!=null){
        stack.push(cur);
        cur = cur.next;
        }
    while(!stack.isEmpty()){
        Node top = stack.pop();
        System.out.print(top.val+" ");
    }
}

面试题3

题目

给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

1.左括号必须用相同类型的右括号闭合。

2.左括号必须以正确的顺序闭合。

来源:力扣(LeetCode)

链接:https://leetcode.cn/problems/valid-parentheses

思路

使用栈进行解答

  1. 遍历字符串成字符

  1. 判断字符是否为括号,是左括号就进栈,遇到右括号时,字符ch2接收栈顶元素为ch2

  1. 判断ch2(左括号)与ch(右括号)是否匹配,匹配就将ch2进行出栈,不匹配返回false

  1. 最后判断栈是否为空,不为空就说明栈内的左括号没有匹配完,左括号多,返回false。

  1. 排除以上情况,返回true

代码实现

public class IsValid {
    public boolean isValid(String s){
        Stack<Character> stack = new Stack<>();
        for (int i = 0; i < s.length(); i++) {
            char ch = s.charAt(i);
            if (ch == '(' || ch == '{' || ch == '['){
                // 左括号进入栈
                stack.push(ch);
            }else {
                //遇见了右括号,1.判断栈里面还有有没有元素,没有就无法匹配这个右括号,返回false
                if(stack.empty()){
                    return false;
                }
                // 遇见了右括号,1. 判断栈里面还有元素,判断左括号和这个右括号是否配对,配对就出栈,不配对就false
                char ch2 = stack.peek();
                if(ch == ')' && ch2 == '(' ||ch == ']' && ch2 == '['||ch == '}' && ch2 == '{'){
                    stack.pop();
                }else {
                    return false;
                }
            }
        }
        if (!stack.empty()){
            // 遍历完成,如果栈里面还有元素,则没有配对成功
            return false;
        }
        // 排除所有的false 返回true
        return true;
    }
}


面试题4

题目

给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。请你计算该表达式。返回一个表示表达式值的整数。

注意:

有效的算符为 '+'、'-'、'*' 和 '/' 。

每个操作数(运算对象)都可以是一个整数或者另一个表达式。

两个整数之间的除法总是 向零截断 。

表达式中不含除零运算。

输入是一个根据逆波兰表示法表示的算术表达式,答案及所有中间计算结果可以用 32 位 整数表示。

来源:力扣(LeetCode)

链接:https://leetcode.cn/problems/evaluate-reverse-polish-notation

思路

使用栈进行解答

  1. 遍历字符串

  1. 判断是否为运算符 isOperation(String x)

  1. 不是运算符进行入栈操作(记得转化为Integer类型(Integer.parseInt(x)))

  1. 是运算符进行出站操作两次分别使用num2接收第一次出站的元素,num1接收第二次出站的元素

  1. 进入switcht语句进行判断运算符的类型,进行计算。

  1. 进行运算num1(运算符)num2, 将运算出的结果进行进栈操作,例如:stack.push(num1+num2);break

  1. 遍历结束,栈内还剩下一个元素,直接返回该元素即可。

代码实现

package Stack;

import java.util.Stack;

/**
 * Created with IntelliJ IDEA.
 * Description:逆波兰表达式求值
 * User: YAO
 * Date: 2023-03-15
 * Time: 16:35
 */
public class EvalRPN {
    public int evalRPN(String[] tokens) {
        Stack<Integer> stack = new Stack<>();
        for (String x:tokens) {
            // 判断是否为运算符,不是运算符选择进栈
            if (!isOperation(x)){
                stack.push(Integer.parseInt(x));
            }else {
                // 出栈操作:num1(操作符)num2
                int num2 = stack.pop();
                int num1 = stack.pop();
                switch (x){
                    case "+":
                        stack.push(num1+num2);
                        break;
                    case "-":
                        stack.push(num1-num2);
                        break;
                   case "*":
                        stack.push(num1*num2);
                        break;
                    case "/":
                        stack.push(num1/num2);
                        break;
                }
            }
        }
        // 此时栈顶元素就是所求值
        return stack.peek();
    }
    private boolean isOperation(String x) {
        // 判断是否为运算符
        return x.equals("+") || x.equals("-") || x.equals("/") || x.equals("*");
    }

}


面试题5

题目

栈的压入、弹出序列

描述:

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

1. 0<=pushV.length == popV.length <=1000

2. -1000<=pushV[i]<=1000

3. pushV 的所有数字均不相同

来源:牛客

链接:https://www.nowcoder.com/practice/d77d11405cc7470d82554cb392585106?tpId=13&&tqId=11174&rp=1&ru=/activity/oj&qru=/ta/coding-interviews/question-ranking

思路

  1. 遍历数组pushA,

  1. 首先进行进栈操作

  1. 定义j=0;用来记录数组popA元组的下标。

  1. 比较popA元素与栈顶元素是否相等,如果相等(stack.peek().equals(popA[j] == true)),进行出栈操作,j进行++,不相等继续进行进栈操作。前提是遍历的次数不能超过数组popA的长度以及栈不能为空。

  1. 最后循环结束,检查栈是否为空,不为空说明popA不是出栈序列。

代码实现

package Stack;
import java.util.Stack;

/**
 * Created with IntelliJ IDEA.
 * Description:栈的弹出压入序列
 * User: YAO
 * Date: 2023-03-15
 * Time: 16:46
 */
public class isPopOrder {

    public boolean IsPopOrder(int [] pushA,int [] popA) {
        Stack<Integer> stack = new Stack<>();
        int j = 0;
        for (int i = 0; i < pushA.length; i++) {
            stack.push(pushA[i]);
            while (!stack.empty()&& j<popA.length && stack.peek().equals(popA[j])){
                stack.pop();
                j++;
            }
        }
        return stack.empty();
    }
}

面试题6

题目

设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。实现 MinStack 类:

1.MinStack() 初始化堆栈对象。

2.void push(int val) 将元素val推入堆栈。

3.void pop() 删除堆栈顶部的元素。

4.int top() 获取堆栈顶部的元素。

5.int getMin() 获取堆栈中的最小元素

来源:力扣(LeetCode)

链接:https://leetcode.cn/problems/min-stack

思路

  1. 定义两个栈 stack minStack

  1. 首先先往stack栈内压栈元素val

  1. 进栈:判断minStack栈内是否有元素,没有元素就将该val进行压栈到minStack,minStack栈内有元素,将该栈顶元素与val进行比较,如果val小于等于minStack栈顶元素,对于minStac进行压栈操作minstack.push(val);.

  1. 出栈:stack正常出栈,但是要和minStack的栈顶元素进行比较,如果相等的话,就代表最小值有变化,对于minStack进行出栈操作,minstack.push(val);

  1. top():判断stack是否为空,不为空返回栈顶元素,为空可以返回-1,也可以设置为抛出异常

  1. getMin():判断minStack是否为空,不为空返回栈顶元素,为空可以返回-1,也可以设置为抛出异常

代码实现

package Stack;

import java.util.Stack;

/**
 * Created with IntelliJ IDEA.
 * Description:最小栈
 * User: YAO
 * Date: 2023-03-15
 * Time: 15:42
 */
public class minStack {
    public Stack<Integer> stack;
    public Stack<Integer> minstack;
    public minStack() {
        stack = new Stack<>();
        minstack = new Stack<>();
    }

    public void push(int val) {
        stack.push(val);
        if (minstack.empty()){
            minstack.push(val);
        }else {
            if(minstack.peek()>=val){
                minstack.push(val);
            }
        }
    }

    public void pop() {
        if (!stack.empty()){
            Integer val = stack.pop();
            //维护最小栈
            if (val.equals(minstack.peek())){
                // 如果
                minstack.pop();
            }
        }
    }

    public int top() {
        if(!stack.empty()){
            return stack.peek();
        }
        return -1;
    }

    public int getMin() {
        if(!minstack.empty()){
            return minstack.peek();
        }
        return -1;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哈士奇的奥利奥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值