题目:
你现在是一场采用特殊赛制棒球比赛的记录员。这场比赛由若干回合组成,过去几回合的得分可能会影响以后几回合的得分。
比赛开始时,记录是空白的。你会得到一个记录操作的字符串列表 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
分析
当前得分的方式有可能是上一次的得分,同时也可能会清空上一次得分,这种很明显适合用先入后出的数据结构,因此栈可以解决这个问题,尤其注意元素是+的时候,先要弹出元素才能取到倒数第二次的分数
同时我们用数组也可以解这个问题,用一个哨兵来标示当前数组的有效位,同时一定要注意最终算总成绩的时候遍历数组不能超过该哨兵(元素是C的时候哨兵会减1,所以哨兵前面的元素才是有效分数)
java
import java.util.Deque;
import java.util.LinkedList;
import java.util.Arrays;
public class baseballGame {
public static void main(String[] args) {
String[] arr = {"5","2","C","D","+"};
System.out.println(getScoreArray(arr));
}
public static int getScoreArray(String[] arr) {
int[] count = new int[arr.length];
int index = 0;
for(String str : arr) {
if("D".equals(str)) {
count[index] = count[index-1] * 2;
index++;
} else if("+".equals(str)) {
count[index] = count[index-1] + count[index-2];
index++;
} else if("C".equals(str)) {
index--;
} else {
count[index] = Integer.valueOf(str);
index++;
}
}
int sum = 0;
for(int i = 0;i<index;i++) {
sum = sum + count[i];
}
return sum;
}
public static int getScore(String[] arr) {
Deque stack = new LinkedList();
for(int i = 0;i<arr.length;i++) {
if(arr[i].charAt(0) == 'C') {
stack.pop();
} else if(arr[i].charAt(0) == 'D') {
int val = (int) stack.peek();
stack.push(val * 2);
} else if(arr[i].charAt(0) == '+') {
int first = (int) stack.peek();
stack.pop();
int second = (int) stack.peek();
stack.push(first);
stack.push(first+second);
} else {
stack.push(Integer.valueOf(arr[i]));
}
}
int sum = 0;
while(stack.size() > 0) {
sum = sum + (int)stack.peek();
stack.pop();
}
return sum;
}
}