From 67048088ffad8d72190c3ec1acf0b5814553517a Mon Sep 17 00:00:00 2001 From: zhangsan <646228430@qq.com> Date: Mon, 31 Mar 2025 18:50:51 +0800 Subject: [PATCH] =?UTF-8?q?3.31=20=E6=A0=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/stack/Calculate.java | 72 ++++++++++++++++++++ src/main/java/stack/Calculate2.java | 77 ++++++++++++++++++++++ src/main/java/stack/DailyTemperatures.java | 46 +++++++++++++ src/main/java/stack/DecodeString.java | 42 +++++++++++- 4 files changed, 236 insertions(+), 1 deletion(-) create mode 100644 src/main/java/stack/Calculate.java create mode 100644 src/main/java/stack/Calculate2.java create mode 100644 src/main/java/stack/DailyTemperatures.java diff --git a/src/main/java/stack/Calculate.java b/src/main/java/stack/Calculate.java new file mode 100644 index 0000000..911b431 --- /dev/null +++ b/src/main/java/stack/Calculate.java @@ -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 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 + } +} diff --git a/src/main/java/stack/Calculate2.java b/src/main/java/stack/Calculate2.java new file mode 100644 index 0000000..e4a2dce --- /dev/null +++ b/src/main/java/stack/Calculate2.java @@ -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 stack = new ArrayDeque(); + 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 + } +} diff --git a/src/main/java/stack/DailyTemperatures.java b/src/main/java/stack/DailyTemperatures.java new file mode 100644 index 0000000..a95c7c5 --- /dev/null +++ b/src/main/java/stack/DailyTemperatures.java @@ -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 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; + } +} diff --git a/src/main/java/stack/DecodeString.java b/src/main/java/stack/DecodeString.java index e439871..626758a 100644 --- a/src/main/java/stack/DecodeString.java +++ b/src/main/java/stack/DecodeString.java @@ -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 countStack = new LinkedList<>(); + Deque 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(); } } \ No newline at end of file