目录
面试题2:输入两个序列,第一个int[] pushA表示栈的压入顺序,判断第二个序列int[] poppA是否为弹出序列。
面试题4:设计一个支持 push ,pop ,top 操作,并在常数时间内检索到最小元素的栈。
1.栈的基本.概念
1.栈:特殊的线性表
在固定的一端(栈顶)进行数据插入与删除,遵循后进先出(Last In First Out,LIFO)原则。
压栈:数据的写入(也叫进栈、入栈); 出栈:数据的删除
2.基本方法:栈的几种主要基本操作:
void push(int data):入栈
int pop():出栈(删除并返回最后一个插入栈的元素)
int peek():查看栈顶元素
boolean empty():判断是否为空
2.栈的实现
1.顺序表实现:利用尾插和尾删的方式实现
注意:入栈之前要先判断顺序表容量是否够,不够则需进行扩容 Arrays.copyOf()
this.elem = Arrays.copyOf(this.elem,2*this.elem.length);
public class MyStack {
public int[] elem;
public int usedSize;
public MyStack() {
this.elem = new int[5];
}
@Override
public String toString() {
return "MyStack{" +
"elem=" + Arrays.toString(elem) +
", usedSize=" + usedSize +
'}';
}
//入栈
public void push(int val) {
if (isFull()) {
//扩容
this.elem = Arrays.copyOf(this.elem,2*this.elem.length); //2倍数扩容
}
this.elem[this.usedSize] = val;
this.usedSize++;
}
public boolean isFull() {
return this.usedSize == this.elem.length;
}
//出栈
public int pop() {
if (isEmpty()) {
throw new RuntimeException("栈为空");
}
int oldValue = this.elem[usedSize-1];
this.usedSize--;
return oldValue;
}
//出栈
public int peek() {
if (isEmpty()) {
throw new RuntimeException("栈为空");
}
return this.usedSize--;
}
}
主函数及其实现
public static void main(String[] args) {
MyStack stack = new MyStack();
stack.push(12);
stack.push(13);
stack.push(14);
stack.push(15);
stack.push(16);
stack.push(17);
System.out.println(stack); //[12, 13, 14, 15]
System.out.println(stack.pop()); //弹出栈顶元素,并删除 15
System.out.println(stack); //[12, 13, 14]
System.out.println(stack.peek()); //弹出栈顶元素,不删除 15
System.out.println(stack); //[12, 13, 14]
System.out.println(stack.isEmpty()); //查询是否为空 false
}
2.链表实现:头尾皆可实现
面试题1:有效字符串的实现
解析:1.左括号入栈, 若遇有括号看是否匹配peek()==[i] 2.若匹配,则出栈; 3.当遍历完字符串栈不为空,则组括号多,反之有括号多
public boolean isValid(String s) {
Stack<Character> stack = new Stack<>(); //给定一个栈用来存放字符
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i); //将字符串s转换为字符
if (ch == '(' || ch == '[' || ch =='{') { //判断是否为左括号,是的话写入栈
stack.push(ch);
}else { //遇到右括号 查看匹配
if (stack.empty()) {
System.out.println("右括号多");
return false;
}
char top = stack.peek(); //获取栈顶元素 是否有与之对应的括号 哪个左括号
if (top == '{' && ch =='}' || top == '[' && ch ==']' ||
top == '(' && ch ==')') {
stack.pop();
}else {
System.out.println("左右括号不匹配");
return false;
}
}
}
if (!stack.empty()) {
System.out.println("左括号多");
return false;
}
return true;
}
面试题2:输入两个序列,第一个int[] pushA表示栈的压入顺序,判断第二个序列int[] poppA是否为弹出序列。
解析:1.遍历第一个序列pushA,将其放入栈里,直到第二个序列的首元素与第一个序列重元素相同,则弹出该元素,j++
public boolean validateStackSequences(int[] pushA, int[] popA) {
Stack<Integer> stack = new Stack<>();
int j = 0; //遍历popA
for (int i = 0; i < pushA.length; i++) {
stack.push(pushA[i]);
//先判断写入stack栈里的元素是否等于压出序列的元素stack.peek() == popA[j]
while (j < popA.length && !stack.empty() && stack.peek() == popA[j]) {
stack.pop(); //弹出元素
j++;
}
}
return stack.empty();
}
面试题3:根据 逆波兰表示法(后缀表达式),求表达式的值
也即是:(5+4)*3-2------>54+3*2-
解析:1.将常量放入栈中,遇到运算符则取出常量,进行运算并将结果放入栈中,继续此过程(遍历表达式找常量放入栈里),完成后缀表达式的计算
public int evalPRN(String[] tokens) {
Stack<Integer> stack = new Stack<>(); //new 一个stack用于存放整数
for (int i = 0; i < tokens.length; i++) {
String val = tokens[i]; //获取元素
if (!isOperatation(val)) { //判断是否是运算符,不是要放入栈里stack.push(val)
stack.push(Integer.parseInt(val)); //不是运算符 ,需要将字符串val转化为整型integer
}else { //确定是什么运算符
int num2 = stack.pop();
int num1 = stack.pop();
switch (val) {
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.pop();
}
//判断是否是运算符
private boolean isOperatation(String x) {
if (x.equals("+") || x.equals("-") || x.equals("*") || x.equals("/")) { //判断是否是运算符的条件
return true;
}
return false;
}
面试题4:设计一个支持 push ,pop ,top 操作,并在常数时间内检索到最小元素的栈。
public class MinStack {
private Stack<Integer> stack;
private Stack<Integer> minStack;
public MinStack() { //构造方法
stack = new Stack<>(); //初始化
minStack = new Stack<>();
}
public void push(int val) {
stack.push(val); //普通栈放入元素--》最小栈则需要先看其是否为空
if (!minStack.empty()) { //不为空 获取最小栈的栈顶元素,与普通栈的元素val进行比较
int top = minStack.peek(); //,val<=最小栈栈顶元素top 则将val其放入最小栈
if(val <= top) {
minStack.push(val); //val更小时,则将其放入最小栈
}
}else { //最小栈为空,执行元素放入最小栈
minStack.push(val);
}
}
//出栈
public void pop() {
int popVal = stack.pop(); //保存普通栈弹出的元素
if (!minStack.empty()) {
int top = minStack.peek(); // 先获取最小栈栈顶的值
if (top == popVal) { //最小栈栈顶值top与普通栈出站的值进行比较
minStack.pop(); //若相等,最小栈栈顶值top则也需要出栈,不等则无需进行操作
}
}
}
public int top() {
return stack.peek();
}
public int getMin() {
return minStack.peek();
}
}