一、题目描述
你现在是一场采用特殊赛制投篮大赛的记录员。这场比赛由若干回合组成,过去几回合的得分可能会影响以后几回合的得分。
比赛开始时,记录是空白的。你会得到一个记录操作的字符串列表 ops,其中ops[i]是你需要记录的第i项操作,ops遵循下述规则:
- 整数x-表示本回合新获得分数x
- "+" -- 表示本回合新获得的得分是前两次得分的总和。
- "D" -- 表示本回合新获得的得分是前一次得分的两倍。
- "C" -- 表示本回合没有分数,并且前一次得分无效,将其从记录中移除。
请你返回记录中所有得分的总和。
二、输入输出描述
输入描述
- 一行字符串,表示操作序列(用空格分隔)
输出描述
- 一个整数,表示所有得分总和
三、示例
|----|-------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 输入 | 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 |
四、解题思路
1. 核心思想
使用栈(Stack) 这种后进先出 的数据结构,完美匹配操作只影响最近一次 / 两次得分的规则,按顺序处理所有操作,最后累加栈中所有有效得分。
2. 问题本质分析
这是一个带历史回退操作的序列计算问题:
- 所有操作(C/D/+)都只针对最近的得分
- 需要频繁获取、撤销、计算最近的记录
- 本质:用栈维护有序的历史记录 + 按规则更新栈 + 最终求和
3. 核心逻辑
- 遍历每个操作,只操作栈顶元素(最近得分);
- 数字直接入栈;C 弹出栈顶(撤销);D 复制栈顶翻倍;+ 取栈顶两个数求和;
- 所有操作完成后,栈中存储的就是全部有效得分;
- 遍历栈求和,输出结果。
4. 步骤拆解
-
输入处理读取一行字符串,按空格分割成操作数组。
-
栈初始化创建空栈,用于存储每一轮的有效得分。
-
遍历处理操作
- 数字:入栈
- C:栈顶出栈(撤销)
- D:栈顶 ×2 入栈
- +:取栈顶两个数求和后入栈
-
计算总得分遍历栈中所有元素,累加得到最终结果。
-
输出总和
五、代码实现
java
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] ops = sc.nextLine().split(" ");
Stack<Integer> stack = new Stack<>();
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 last1 = stack.pop();
int last2 = stack.peek();
stack.push(last1);
stack.push(last1 + last2);
} else {
// 数字,直接入栈
stack.push(Integer.parseInt(op));
}
}
// 计算总和
int sum = 0;
for (int num : stack) {
sum += num;
}
System.out.println(sum);
}
}