1.括号匹配问题OJ
思路
- 利用栈的先进后出特性
- 左括号入栈
- 遇到右括号,这是就应该开始一一对比
- 不相等的情况无非是
括号不匹配
,左括号多
,右括号多
- 三种情况全部排查完毕之后则说明括号完全匹配
private static boolean isValid(String str) {
if (str.length() == 0 || str.length() % 2 != 0) {
return false;
} else if (str == null) {
return false;
} else {
Stack<Character> stack = new Stack<>();
/*
不匹配的三种可能
1. 左括号多,字符串为空
2. 栈空, 字符串多
3. 上来就不匹配
遍历字符串,左括号入栈,右括号和栈顶元素比较
*/
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if (ch == '{' || ch == '[' || ch == '(') {
stack.push(ch);
} else{
// 遇到右括号
// 栈为空
if (stack.empty()) {
// 【右括号多】
return false;
} else {
// 栈不为空
char tmp = stack.peek();
if (tmp == '{' && ch == '}' || tmp == '[' && ch == ']' || tmp == '(' && ch == ')'){
stack.pop();// 相等就弹出
}else{
return false;// 左右括号不匹配
}
}
}
}
if (!stack.empty()){
return false;// 左括号多
}
return true;
}
}
2.用队列实现栈OJ
思路
- 利用两个队列,只需要让不为空的进出队列即可
- 如果两个队列都不为空,则让其中某一个队列存储元素
peek
和pop
操作记得控制好空
这一边界条件
public class MyStack {
public Queue<Integer> qu1 = new LinkedList<>();
public Queue<Integer> qu2 = new LinkedList<>();
/**
* 入栈
* 哪个不为空,哪个就存储
* 如果都不为空,就制定其中一个存储即可
* @param x 值
*/
public void push(int x) {
if (!qu1.isEmpty()) {
qu1.offer(x);
} else if (!qu2.isEmpty()) {
qu2.offer(x);
} else {
qu1.offer(x);
}
}
/**
* 出栈
* 先弹出 size - 1 个元素,每次均保留下来弹出的元素并让另一个队列存储
* 最后再弹出剩余的那个元素,也就是队列最后一个元素【队列最后一个元素进入】就达到栈的的先进后出的功能
* @return
*/
public int pop() {
if (empty()) {
return -1;
}
int e = -1;
if (!qu1.isEmpty()) {
int sz = qu1.size() - 1;
while (sz-- != 0) {
e = qu1.poll();
qu2.offer(e);
}
e = qu1.poll();
} else {
int sz = qu2.size() - 1;
while (sz-- != 0) {
e = qu2.poll();
qu1.offer(e);
}
e = qu2.poll();
}
return e;
}
/**
* 得栈顶元素不删除
* 需要弹出 size 个元素并记录保留,作为入另一个队列元素和返回值
* @return
*/
public int top() {
if (empty()){
return -1;
}else{
int e = -1;
if (!qu1.isEmpty()){
int sz = qu1.size();
while(sz--!=0){
e = qu1.poll();
qu2.offer(e);
}
}else{
int sz = qu1.size();
while(sz--!=0){
e = qu1.poll();
qu2.offer(e);
}
}
return e;
}
}
public boolean empty() {
return qu1.isEmpty() && qu2.isEmpty();
}
}
在这里插入图片描述
如图所示就是一次“出栈pop”操作
- ABCDEF 先入队列
- 把一个不为空的队列queue1元素 ABCDE 搬入到另一个队列queue2中
- queue1 再出队列,这样就实现了“先进后出【后进先出】”的功能
3.用栈实现队列OJ
两个指定的栈实现队列
只需要制定一个栈入一个栈出即可达到队列的先进先出效果
public class MyyQueue {
Stack<Integer> stack1 = new Stack<>();
Stack<Integer> stack2 = new Stack<>();
public void push(int x){
stack1.push(x);
}
public int pop(){
if (empty()){
return -1;
}else {
if (stack2.empty()){
while (!stack1.empty()){
// 把栈1出完全部存入栈2
stack2.push(stack1.pop());
}
}
return stack2.pop();//弹出栈2栈顶元素
}
}
public int peek(){
if (empty()){
return -1;
}else {
if (stack2.empty()){
while (!stack1.empty()){
stack2.push(stack1.pop());
}
}
return stack2.peek();
}
}
public boolean empty(){
return stack1.empty() && stack2.empty();
}
}
4.实现一个最小栈OJ
设计两个栈
- 一个栈
stack
存储所有元素,minStack
只存储stack当前中小的元素,按次序存储
public class MinStack {
Stack<Integer> stack = new Stack<>();
Stack<Integer> minStack = new Stack<>();
public void push(int val){
stack.push(val);
if (minStack.empty()){
minStack.push(val);
}else{
if (minStack.peek() <= val){
// 如果存储了两个比 minStack 栈顶还小的元素,当 stack 弹出栈中的元素刚好和 minStack 栈顶一样的时候两个都需要弹出,因此需要包含相同的最小值存入 minStack 中
minStack.push(val);
}
}
}
public void pop(){
if (stack.pop() == minStack.peek()){
minStack.pop();// 不可以把 minStack 的元素忽略掉
}
}
public int top(){
return stack.peek();
}
public int getMin(){
return minStack.peek();
}
}
5. 设计循环队列OJ
循环队列的详细剖析请查看我之前博客内容
class MyCircularQueue {
private int[] elem;
private int front, rear;
public MyCircularQueue(int k) {
this.elem = new int[k+1];
}
/**
* 入队列
*
* @param value 值
* @return
*/
public boolean enQueue(int value) {
if ((this.rear + 1) % this.elem.length == this.front) {
return false;//满了
} else {
this.elem[this.rear] = value;
this.rear = (this.rear + 1) % this.elem.length;
return true;
}
}
/**
* 出队列
*
* @return
*/
public boolean deQueue() {
if (this.front == this.rear) {
return false;
} else {
int val = this.elem[this.front];
// this.front = (this.front + 1) % this.elem.length;// 因为是循环,所以不能直接 front+1
return true;
}
}
/**
* 取队头元素【相当于 peek 】
*
* @return
*/
public int Front() {
if (this.front == this.rear) {
return -1;// leetcode 抛异常会认为是你的代码错误,所以不能抛异常
} else {
int val = this.elem[this.front];
return val;
}
}
/**
* 取队尾元素
* rear处于0位置则返回this.elem.length-1
* 所以不能直接进行 -1 操作
*
* @return
*/
public int Rear() {
if (this.rear == this.front) {
return -1;
} else {
if (this.rear == 0) {
return this.elem[this.elem.length - 1];
} else {
return this.elem[this.rear - 1];
}
}
}
public boolean isEmpty() {
return this.front == this.rear;
}
public boolean isFull() {
return this.rear + 1 == this.front;
}
}