Hi~!这里是奋斗的明志,很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~~
🌱🌱个人主页:奋斗的明志
🌱🌱所属专栏:数据结构
📚本系列文章为个人学习笔记,在这里撰写成文一为巩固知识,二为展示我的学习过程及理解。文笔、排版拙劣,望见谅。
文章目录
前言
- 栈、虚拟机栈、栈帧有什么区别呢?
- 栈 ---- 数据结构
- 虚拟机栈 ---- JVM内存
- 栈帧 ---- 调用方法的时候开辟的内存
一、有效的括号
1.题目
2.解析
3.代码展示
class Solution {
//s为字符串
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{
//如果不是左括号
//栈为空
if(stack.isEmpty()){
return false;
}
//栈不为空
//拿到栈顶元素
//看是否匹配
char tmp = stack.peek();
if(tmp == '(' && ch == ')'){
stack.pop();
}else if(tmp == '{' && ch == '}'){
stack.pop();
}else if(tmp == '[' && ch == ']'){
stack.pop();
}else{
return false;
}
}
}
//字符串遍历完了,栈不为空
//例如: ( ( )
if(!stack.isEmpty()){
return false;
}
return true;
}
}
二、逆波兰表达式求值
1.题目
2.解析
【说明】
- 对遍历的每个元素进行判断
- 如果是数字进行压栈
- 如果是运算符,依次从栈里面弹出两个元素
- 进行相对应的运算符操作
主要方法 evalRPN 解析:
- evalRPN 方法接收一个字符串数组 tokens,每个元素可以是操作数或运算符。
- 创建一个 Stack 类型的栈 stack,用于存储操作数。
- 遍历 tokens 数组,对每个元素进行判断:
- 如果是操作数(通过 isOperation 方法判断是否为运算符),将其转换为整数并压入栈中。
- 如果是运算符,从栈中弹出两个操作数(注意先弹出的是 num1,后弹出的是 num2,因为栈是先进后出的),根据运算符进行相应的运算,将结果压入栈中。
- 最终,栈中剩余的唯一元素即为整个表达式的计算结果。
辅助方法 isOperation 解析:
- isOperation 方法简单地判断字符串是否为 +、-、* 或 / 中的一个,用于区分操作数和运算符。
3.代码展示
class Solution {
public int evalRPN(String[] tokens) {
Stack<Integer> stack = new Stack<>();
// 进行遍历
for (int i = 0; i < tokens.length; i++) {
String str = tokens[i];
if (!isOperations(str)) {
// 进行压栈操作
// 将字符串转换为整形
int val = Integer.valueOf(str);
stack.push(val);
} else {
// 说明是运算符
// 取出栈里面的最上面两个元素
int num2 = stack.pop();
int num1 = stack.pop();
// 进行完 运算符操作后 结果进行压栈处理
switch (str) {
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();
}
/**
* 写一个方法,对运算符进行判断
*/
public boolean isOperations(String str) {
if (str.equals("+") || str.equals("-") || str.equals("*") || str.equals("/")) {
return true;
}
return false;
}
}
三、栈的压入、弹出序列
1.题目
2.解析
j
是popV
数组的索引,用于遍历弹出顺序数组。stack
是一个栈,用来模拟入栈和出栈操作。- 遍历
pushV
数组,依次将元素压入栈中。 - 每次入栈后,通过一个 while 循环检查栈顶元素是否与当前 popV 数组指定的弹出顺序相符:
- 如果栈顶元素与
popV[j]
相等,则执行出栈操作(即弹出栈顶元素),并将 j 向后移动一位。 - 循环执行直到栈顶元素不再与
popV[j]
相等或者栈为空。
- 如果栈顶元素与
- 这样可以模拟出栈的过程,检查是否能按照
popV
的顺序完整弹出。 - 最终判断条件是
j
是否达到了popV
数组的长度。如果达到了,说明所有的弹出操作都按照正确的顺序进行了,返回 true;否则返回 false。
3.代码展示
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param pushV int整型一维数组
* @param popV int整型一维数组
* @return bool布尔型
*/
public boolean IsPopOrder (int[] pushV, int[] popV) {
// write code here
int j = 0;
Stack<Integer> stack = new Stack<>();
for (int i = 0; i < pushV.length; i++) {
stack.push(pushV[i]);
while (!stack.isEmpty() && j < popV.length && stack.peek() == popV[j]) {
stack.pop();
j++;
}
}
return j >= popV.length;
}
}
四、最小栈
1.题目
2.解析
【注意】
要创建两个栈才能完成 在常数时间内检索
3.代码展示
class MinStack {
// 定义两个栈
// 一个正常存元素
// 一个存最小的
Stack<Integer> stack;
Stack<Integer> minStack;
public MinStack() {
stack = new Stack<>();
minStack = new Stack<>();
}
public void push(int val) {
// 普通栈必须要放
stack.push(val);
// 最小栈,刚开始栈为空的时候也要放
if (minStack.isEmpty()) {
minStack.push(val);
} else {
if (val <= minStack.peek()) {
minStack.push(val);
}
}
}
public void pop() {
// 从普通栈 弹出
int val = stack.pop();
// 从最小栈 弹出
if (val == minStack.peek()) {
minStack.pop();
}
}
public int top() {
return stack.peek();
}
public int getMin() {
return minStack.peek();
}
}
/**
* Your MinStack object will be instantiated and called as such:
* MinStack obj = new MinStack();
* obj.push(val);
* obj.pop();
* int param_3 = obj.top();
* int param_4 = obj.getMin();
*/
总结
在 Java 中,
Integer.valueOf()
和Integer.parseInt()
都是用来将字符串转换为整数 (int) 的方法,但它们有一些区别:
返回类型:
Integer.valueOf(String str)
返回一个Integer
对象。Integer.parseInt(String str)
返回一个基本数据类型int
。
String str = "123";
Integer valueOfResult = Integer.valueOf(str); // 返回 Integer 对象
int parseIntResult = Integer.parseInt(str); // 返回 int 值
缓存机制:
Integer.valueOf(String str)
方法内部使用了一个缓存机制,它会缓存整数值在 -128 到 127 范围内的对象实例。因此,对于这个范围内的整数,多次调用 valueOf() 方法会返回相同的对象实例,而不是每次都创建一个新对象。这可以提高性能并节省内存。- Integer.parseInt(String str) 方法则没有缓存机制,每次调用都会新建一个 int 类型的值。
异常处理:
Integer.valueOf(String str)
方法会抛出NumberFormatException
异常,如果字符串无法转换为整数。Integer.parseInt(String str)
也会抛出NumberFormatException
异常,如果字符串无法转换为整数。