逆波兰表达式求值
根据 逆波兰表示法,求表达式的值。
有效的算符包括 +、-、*、/ 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。
说明:
整数除法只保留整数部分。
给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。
示例 1:
输入:tokens = [“2”,“1”,"+",“3”,"*"]
输出:9
解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9
示例 2:
输入:tokens = [“4”,“13”,“5”,"/","+"]
输出:6
解释:该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6
示例 3:
输入:tokens = [“10”,“6”,“9”,“3”,"+","-11","*","/","*",“17”,"+",“5”,"+"]
输出:22
解释:
该算式转化为常见的中缀算术表达式为:
((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22
辅助栈
class Solution {
public int evalRPN(String[] tokens) {
Deque<Integer> stack = new LinkedList<Integer>();
int n = tokens.length;
for (int i = 0; i < n; i++) {
String token = tokens[i];
if (isNumber(token)) {
stack.push(Integer.parseInt(token));
} else {
int num2 = stack.pop();
int num1 = stack.pop();
switch (token) {
case "+":
stack.push(num1 + num2);
break;
case "-":
stack.push(num1 - num2);
break;
case "*":
stack.push(num1 * num2);
break;
case "/":
stack.push(num1 / num2);
break;
default:
}
}
}
return stack.pop();
}
public boolean isNumber(String token) {
return !("+".equals(token) || "-".equals(token) || "*".equals(token) || "/".equals(token));
}
}
数组模拟
class Solution {
public int evalRPN(String[] tokens) {
int n = tokens.length;
int[] stack = new int[(n + 1) / 2];
int index = -1;
for (int i = 0; i < n; i++) {
String token = tokens[i];
switch (token) {
case "+":
index--;
stack[index] += stack[index + 1];
break;
case "-":
index--;
stack[index] -= stack[index + 1];
break;
case "*":
index--;
stack[index] *= stack[index + 1];
break;
case "/":
index--;
stack[index] /= stack[index + 1];
break;
default:
index++;
stack[index] = Integer.parseInt(token);
}
}
return stack[index];
}
}
有效的括号
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
示例 1:
输入:s = “()”
输出:true
示例 2:
输入:s = “()[]{}”
输出:true
示例 3:
输入:s = “(]”
输出:false
示例 4:
输入:s = “([)]”
输出:false
示例 5:
输入:s = “{[]}”
输出:true
辅助栈
class Solution {
public boolean isValid(String s) {
Map<Character,Character> map = new HashMap<Character,Character>(){{
put('{','}'); put('[',']'); put('(',')');
}};
if (s.length() > 0 && !map.containsKey(s.charAt(0)))
return false;
LinkedList<Character> stack = new LinkedList<>();
for(Character c : s.toCharArray()){
if(map.containsKey(c)) {
stack.push(c);
} else if(stack.isEmpty() || map.get(stack.pop()) != c) {
return false;
}
}
return stack.isEmpty();
}
}
简化路径
给你一个字符串 path ,表示指向某一文件或目录的 Unix 风格 绝对路径 (以 ‘/’ 开头),请你将其转化为更加简洁的规范路径。
在 Unix 风格的文件系统中,一个点(.)表示当前目录本身;此外,两个点 (…) 表示将目录切换到上一级(指向父目录);两者都可以是复杂相对路径的组成部分。任意多个连续的斜杠(即,’//’)都被视为单个斜杠 ‘/’ 。 对于此问题,任何其他格式的点(例如,’…’)均被视为文件/目录名称。
请注意,返回的 规范路径 必须遵循下述格式:
- 始终以斜杠 ‘/’ 开头。
- 两个目录名之间必须只有一个斜杠 ‘/’ 。
- 最后一个目录名(如果存在)不能 以 ‘/’ 结尾。
- 此外,路径仅包含从根目录到目标文件或目录的路径上的目录(即,不含 ‘.’ 或 ‘…’)。
返回简化后得到的 规范路径 。
示例 1:
输入:path = “/home/”
输出:"/home"
解释:注意,最后一个目录名后面没有斜杠。
示例 2:
输入:path = “/…/”
输出:"/"
解释:从根目录向上一级是不可行的,因为根目录是你可以到达的最高级。
示例 3:
输入:path = “/home//foo/”
输出:"/home/foo"
解释:在规范路径中,多个连续斜杠需要用一个斜杠替换。
示例 4:
输入:path = “/a/./b/…/…/c/”
输出:"/c"
辅助栈
class Solution {
public String simplifyPath(String path) {
int len = path.length();
List<String> names = new ArrayList<>();
for (int i = 0; i < len; i++) {
if (path.charAt(i) != '/') {
int j = i;
while (j < len && path.charAt(j) != '/') {
j++;
}
names.add(path.substring(i, j));
i = j;
}
}
List<String> res = new ArrayList<>();
for (String name : names) {
if (name.equals("..")) {
if (res.size() > 0)
res.remove(res.size() - 1);
} else if (!name.equals(".")) {
res.add(name);
}
}
return "/" + String.join("/", res);
}
}
字符串解码
给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。
你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。
此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。
示例 1:
输入:s = “3[a]2[bc]”
输出:“aaabcbc”
示例 2:
输入:s = “3[a2[c]]”
输出:“accaccacc”
示例 3:
输入:s = “2[abc]3[cd]ef”
输出:“abcabccdcdcdef”
示例 4:
输入:s = “abc3[cd]xyz”
输出:“abccdcdcdxyz”
辅助栈
class Solution {
public String decodeString(String s) {
StringBuilder result = new StringBuilder();
int k = 0;
Deque<Integer> kStack = new LinkedList<>();
Deque<String> strStack = new LinkedList<>();
for(char c : s.toCharArray()) {
if (c >= '0' && c <= '9') {
k = k * 10 + c - '0';
} else if (c == '[') {
kStack.push(k);
strStack.push(result.toString());
k = 0;
result = new StringBuilder();
} else if(c == ']') {
StringBuilder repeatStr = new StringBuilder();
int repeat = kStack.pop();
while (repeat-- > 0)
repeatStr.append(result);
result = new StringBuilder(strStack.pop());
result.append(repeatStr);
} else {
result.append(c);
}
}
return result.toString();
}
}
递归
class Solution {
public String decodeString(String s) {
StringBuilder sb = new StringBuilder();
int len = s.length();
for (int i = 0; i < len; i++) {
if (s.charAt(i) > '9') {
sb.append(s.charAt(i));
} else {
int k = 0;
while (s.charAt(i) >= '0' && s.charAt(i) <= '9')
k = k * 10 + s.charAt(i++) - '0';
int start = i + 1, open = 1;
while (open > 0) {
i++;
if (s.charAt(i) == '[')
open++;
else if (s.charAt(i) == ']')
open--;
}
int end = i;
while (k-- > 0)
sb.append(decodeString(s.substring(start, end)));
}
}
return sb.toString();
}
}
棒球比赛
你现在是一场采用特殊赛制棒球比赛的记录员。这场比赛由若干回合组成,过去几回合的得分可能会影响以后几回合的得分。
比赛开始时,记录是空白的。你会得到一个记录操作的字符串列表 ops,其中 ops[i] 是你需要记录的第 i 项操作,ops 遵循下述规则:
- 整数 x - 表示本回合新获得分数 x
- “+” - 表示本回合新获得的得分是前两次得分的总和。题目数据保证记录此操作时前面总是存在两个有效的分数。
- “D” - 表示本回合新获得的得分是前一次得分的两倍。题目数据保证记录此操作时前面总是存在一个有效的分数。
- “C” - 表示前一次得分无效,将其从记录中移除。题目数据保证记录此操作时前面总是存在一个有效的分数。
请你返回记录中所有得分的总和。
示例 1:
输入:ops = [“5”,“2”,“C”,“D”,"+"]
输出:30
解释:
“5” - 记录加 5 ,记录现在是 [5]
“2” - 记录加 2 ,记录现在是 [5, 2]
“C” - 使前一次得分的记录无效并将其移除,记录现在是 [5].
“D” - 记录加 2 * 5 = 10 ,记录现在是 [5, 10].
“+” - 记录加 5 + 10 = 15 ,记录现在是 [5, 10, 15].
所有得分的总和 5 + 10 + 15 = 30
示例 2:
输入:ops = [“5”,"-2",“4”,“C”,“D”,“9”,"+","+"]
输出:27
解释:
“5” - 记录加 5 ,记录现在是 [5]
“-2” - 记录加 -2 ,记录现在是 [5, -2]
“4” - 记录加 4 ,记录现在是 [5, -2, 4]
“C” - 使前一次得分的记录无效并将其移除,记录现在是 [5, -2]
“D” - 记录加 2 * -2 = -4 ,记录现在是 [5, -2, -4]
“9” - 记录加 9 ,记录现在是 [5, -2, -4, 9]
“+” - 记录加 -4 + 9 = 5 ,记录现在是 [5, -2, -4, 9, 5]
“+” - 记录加 9 + 5 = 14 ,记录现在是 [5, -2, -4, 9, 5, 14]
所有得分的总和 5 + -2 + -4 + 9 + 5 + 14 = 27
示例 3:
输入:ops = [“1”]
输出:1
辅助栈
class Solution {
public int calPoints(String[] ops) {
Deque<Integer> stack = new LinkedList<>();
for (String op : ops) {
if (op.equals("C")) {
stack.pop();
} else if (op.equals("D")) {
stack.push(stack.peek() * 2);
} else if (op.equals("+")) {
int peek = stack.pop();
int cur = peek + stack.peek();
stack.push(peek);
stack.push(cur);
} else {
stack.push(Integer.parseInt(op));
}
}
int result = 0;
for (int score : stack)
result += score;
return result;
}
}
辅助数组
class Solution {
public int calPoints(String[] ops) {
int[] scores = new int[ops.length];
int idx = 0, result = 0;
for (String op : ops) {
if (op.equals("C")) {
result -= scores[--idx];
continue;
} else if (op.equals("D")) {
scores[idx] = scores[idx - 1] * 2;
} else if (op.equals("+")) {
scores[idx] = scores[idx - 1] + scores[idx - 2];
} else {
scores[idx] = Integer.parseInt(op);
}
result += scores[idx++];
}
return result;
}
}