1. 最小栈(MinStack)实现
- 原理:通过两个栈实现, stack1 保存正常进出栈元素,提供 push 、 pop 、 top 方法功能; stack2 保存当前 stack1 中的最小值,确保其栈顶元素始终是最小值。
- 代码示例
class MinStack {
private Stack<Integer> stack1;
private Stack<Integer> stack2;
public MinStack() {
stack1 = new Stack<>();
stack2 = new Stack<>();
}
public void push(int val) {
stack1.push(val);
if (stack2.isEmpty() || val <= stack2.peek()) {
stack2.push(val);
}
}
public void pop() {
if (stack1.pop().equals(stack2.peek())) {
stack2.pop();
}
}
public int top() {
return stack1.peek();
}
public int getMin() {
return stack2.peek();
}
}
2. 判断栈的弹出序列
- 题目:输入两个整数序列,判断第二个序列是否为第一个序列表示栈的弹出顺序。
- 解题思路
1. 创建一个栈。
2. 遍历入栈序列,元素依次入栈。
3. 每次入栈一个元素后,与出栈序列当前元素比较,若栈顶元素等于出栈序列当前元素,则出栈并移动出栈序列指针,否则继续入栈。
4. 入栈序列遍历完后,若栈为空则返回 true ,否则返回 false 。
- 代码示例
public boolean IsPopOrder(int[] pushA, int[] popA) {
if (pushA == null || popA == null || pushA.length == 0 || popA.length == 0) {
return false;
}
Stack<Integer> stack = new Stack<>();
int popIndex = 0;
for (int num : pushA) {
stack.push(num);
while (!stack.isEmpty() && stack.peek() == popA[popIndex]) {
stack.pop();
popIndex++;
}
}
return stack.isEmpty();
}
3. 逆波兰表达式求值
- 原理:逆波兰表达式是后缀表达式,遇到数字入栈,遇到运算符取出栈顶两个数字运算,结果再入栈,最终栈中唯一元素为表达式结果。
- 代码示例
public int evalRPN(String[] tokens) {
Stack<Integer> stack = new Stack<>();
for (String token : tokens) {
if ("+".equals(token)) {
stack.push(stack.pop() + stack.pop());
} else if ("-".equals(token)) {
int num2 = stack.pop();
int num1 = stack.pop();
stack.push(num1 - num2);
} else if ("*".equals(token)) {
stack.push(stack.pop() * stack.pop());
} else if ("/".equals(token)) {
int num2 = stack.pop();
int num1 = stack.pop();
stack.push(num1 / num2);
} else {
stack.push(Integer.parseInt(token));
}
}
return stack.pop();
}
4. 队列相关
- 接口定义: Queue 是接口,常见方法有 add(E e) 、 offer(E e) 、 remove() 、 poll() 、 element() 、 peek() 等。
- 实现类示例: LinkedList 实现了 Queue 接口。
import java.util.LinkedList;
import java.util.Queue;
public class QueueExample {
public static void main(String[] args) {
Queue<Integer> queue = new LinkedList<>();
queue.add(1);
queue.offer(2);
System.out.println(queue.poll());
System.out.println(queue.peek());
}
}
5. 栈的入栈出栈操作序列分析
通过示例展示不同入栈出栈操作组合下,元素的进出顺序,以及如何根据输入顺序判断能否得到特定输出顺序。
6. 逆序打印单链表
- 递归实现思路:利用递归,先递归到链表末尾,再从末尾开始依次打印节点值。
- 代码示例
class ListNode {
int val;
ListNode next;
ListNode(int val) {
this.val = val;
}
}
public class ReversePrintList {
public static void reversePrint(ListNode head) {
if (head != null) {
reversePrint(head.next);
System.out.print(head.val + " ");
}
}
public static void main(String[] args) {
ListNode a = new ListNode(1);
ListNode b = new ListNode(2);
ListNode c = new ListNode(3);
ListNode d = new ListNode(4);
a.next = b;
b.next = c;
c.next = d;
reversePrint(a);
}
}
7. 有效的括号
- 题目:给定只包含 () 、 [] 、 {} 的字符串,判断是否有效。
- 解题思路:用栈存储左括号,遇到右括号时与栈顶左括号匹配,匹配则出栈,不匹配或栈空则返回 false ,遍历完字符串后栈空则有效。
- 代码示例
public boolean isValid(String s) {
Stack<Character> stack = new Stack<>();
for (char c : s.toCharArray()) {
if (c == '(') {
stack.push(')');
} else if (c == '[') {
stack.push(']');
} else if (c == '{') {
stack.push('}');
} else if (stack.isEmpty() || c != stack.pop()) {
return false;
}
}
return stack.isEmpty();
}