This commit is contained in:
zhangsan 2025-03-31 18:50:51 +08:00
parent 282edf97ec
commit 67048088ff
4 changed files with 236 additions and 1 deletions

View File

@ -0,0 +1,72 @@
package stack;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.LinkedList;
/**
* 题目 224. 基本计算器 (calculate)
* 描述给你一个字符串表达式 s 请你实现一个基本计算器来计算并返回它的值
* 注意:不允许使用任何将字符串作为数学表达式计算的内置函数比如 eval()
* s 由数字'+''-''('')' ' ' 组成
* s 表示一个有效的表达式
* '+' 不能用作一元运算(例如 "+1" "+(2 + 3)" 无效)
* '-' 可以用作一元运算( "-1" "-(2 + 3)" 是有效的)
*
* 示例 1
输入s = "(1+(4+5+2)-3)+(6+8)"
输出23
* 链接https://leetcode.cn/problems/basic-calculator/
*/
//困难题学思路
public class Calculate {
//1 + (3 - 2) - (6 - (4 + 5)) = 1 + 3 - 2 - 6 + 4 + 5
/**
* 栈是用来管理每一层的符号的由于括号可以嵌套所以每一层的计算符号加号或减号可能不同
* 我们通过栈来保存每一层的符号当进入一个新的括号时将当前符号推入栈中当退出括号时弹出栈中的符号回到上一层的符号
*/
public int calculate(String s) {
Deque<Integer> st = new ArrayDeque<>(); // 存放每一层的符号一个括号表示一层
int sign = 1; // 值为1或-1表示当前数的符号
st.push(sign); // 最顶层的符号为+1
int res = 0; // 结果
int number;
int n = s.length();
int i = 0;
char ch;
while(i < n){
if(Character.isDigit(ch = s.charAt(i))){
// 如果为数字生成数值
number = 0;
while(i < n && Character.isDigit(ch = s.charAt(i))){
number = number * 10 + (ch - '0');
i++;
}
// 累加和真实数字等于符号乘以数值
res += sign * number;
}else{
if(ch == '+'){
sign = st.peek(); // 加号获取当前层的符号
}else if(ch == '-'){
sign = -st.peek(); // 减号获取当前层的相反符号
}else if(ch == '('){
st.push(sign); // 左括号进入新一层将当前层符号入栈
}else if(ch == ')'){
st.pop(); // 右括号完成一层的运算弹出这一层符号
}
i++; // 索引右移
}
}
return res;
}
// 测试代码
public static void main(String[] args) {
Calculate solution = new Calculate();
String s = "(1+(4+5+2)-3)-(6+8)";
System.out.println("输入: " + s);
System.out.println("输出: " + solution.calculate(s)); // 输出 23
}
}

View File

@ -0,0 +1,77 @@
package stack;
import java.util.ArrayDeque;
import java.util.Deque;
/**
* 题目 227. 基本计算器 II (calculate2)
* 描述给你一个字符串表达式 s 请你实现一个基本计算器来计算并返回它的值
* 整数除法仅保留整数部分
* 你可以假设给定的表达式总是有效的所有中间结果将在 [-231, 231 - 1] 的范围内
*
* 示例 1
输入s = " 3+5 / 2 "
输出5
* 链接https://leetcode.cn/problems/basic-calculator-ii/
*/
//不会 学下思路
public class Calculate2 {
/**
1. 操作符优先级
首先要理解一个重要的点乘法和除法的优先级高于加法和减法因此在计算过程中需要按照操作符的优先级来处理
乘法*和除法/ 立即计算的一旦遇到它们就需要把栈中的前一个数与当前的数字一起计算
加法+和减法- 延迟计算的它们需要在下一步遇到新的操作符时计算 => 最后统一计算栈中的元素之和
2. 栈的使用
栈是用来存储每个数值的我们将每个数值根据其操作符的类型加法减法乘法或除法计算后放入栈中
*/
//s = " 3+5 / 2 "
public int calculate(String s) {
Deque<Integer> stack = new ArrayDeque<Integer>();
char preSign = '+';
int num = 0;
int n = s.length();
for (int i = 0; i < n; ++i) {
if (Character.isDigit(s.charAt(i))) {
num = num * 10 + s.charAt(i) - '0';
}
if (!Character.isDigit(s.charAt(i)) && s.charAt(i) != ' ' || i == n - 1) {
switch (preSign) {
case '+':
stack.push(num);
break;
case '-':
stack.push(-num);
break;
case '*':
stack.push(stack.pop() * num);
break;
default:
stack.push(stack.pop() / num);
}
preSign = s.charAt(i);
num = 0;
}
}
int ans = 0;
while (!stack.isEmpty()) {
ans += stack.pop();
}
return ans;
}
public static void main(String[] args) {
Calculate2 calculator = new Calculate2();
// 测试用例 1
String expression1 = "3+5/2";
System.out.println("输入: " + expression1);
System.out.println("输出: " + calculator.calculate(expression1)); // 期望输出 5
// 测试用例 2
String expression2 = "3+2*2";
System.out.println("输入: " + expression2);
System.out.println("输出: " + calculator.calculate(expression2)); // 期望输出 7
}
}

View File

@ -0,0 +1,46 @@
package stack;
import java.util.ArrayDeque;
import java.util.Deque;
/**
* 题目 739. 每日温度 (dailyTemperatures)
* 描述给定一个整数数组 temperatures 表示每天的温度返回一个数组 answer 其中 answer[i] 是指对于第 i 下一个更高温度出现在几天后如果气温在这之后都不会升高请在该位置用 0 来代替
* 示例 1
输入: temperatures = [73,74,75,71,69,72,76,73]
输出: [1,1,4,2,1,1,0,0]
* 链接https://leetcode.cn/problems/daily-temperatures/
*/
//第一次做没想到怎么利用栈
public class DailyTemperatures {
public int[] dailyTemperatures(int[] temperatures) {
// 结果数组初始化为全零
int[] result = new int[temperatures.length];
// 存储温度的下标
Deque<Integer> stack = new ArrayDeque<>();
// 遍历整个温度数组
for (int i = 0; i < temperatures.length; i++) {
// 当前温度
int currentTemperature = temperatures[i];
// 处理栈中的元素直到栈为空或者栈顶的温度大于当前温度
while (!stack.isEmpty() && temperatures[stack.peek()] < currentTemperature) {
// 获取栈顶的下标
int prevIndex = stack.pop();
// 计算当前温度和栈顶温度之间的天数差并赋值给结果数组
result[prevIndex] = i - prevIndex;
}
// 当前下标压入栈
stack.push(i);
}
// 返回最终的结果数组
return result;
}
}

View File

@ -1,4 +1,9 @@
package stack;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.LinkedList;
/**
* 题目 394. 字符串解码 (decodeString)
* 描述给定一个经过编码的字符串返回它解码后的字符串
@ -12,8 +17,43 @@ package stack;
* 链接https://leetcode.cn/problems/search-in-rotated-sorted-array/
*/
//不会 有难度
public class DecodeString {
//s = "3[a]2[bc]" "3[a2[c]]"
public String decodeString(String s) {
return "";
// 定义两个栈
Deque<Integer> countStack = new LinkedList<>();
Deque<StringBuilder> stringStack = new LinkedList<>();
StringBuilder current = new StringBuilder();
int k = 0; // 用于保存数字
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
if (Character.isDigit(ch)) {
// 可能有多位数字所以需要乘10再加当前数字
k = k * 10 + (ch - '0');
} else if (ch == '[') {
// 遇到左括号先将当前数字和字符串入栈
countStack.push(k);
stringStack.push(current);
// 重置 k current
k = 0;
current = new StringBuilder();
} else if (ch == ']') {
// 当我们遇到 ']' 可以从栈中取出上一层的字符串并将当前解码的部分附加到这个上一层的字符串后面
int count = countStack.pop();
StringBuilder decoded = stringStack.pop();
// 将当前字符串重复 count 次后追加到上层字符串中
for (int j = 0; j < count; j++) {
decoded.append(current);
}
current = decoded;
} else {
// 普通字符直接追加
current.append(ch);
}
}
return current.toString();
}
}