1、#1047删除字符串中所有相邻重复项
(1)、题目
难度:简单
给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
示例:
输入:“abbaca”
输出:“ca”
解释:
例如,在 “abbaca” 中,我们可以删除 “bb” 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 “aaca”,其中又只有 “aa” 可以执行重复项删除操作,所以最后的字符串为 “ca”。
(2)、解题
栈的方法
我们可以用栈来维护没有重复项的字母序列:
- 若当前的字母和栈顶的字母相同,则弹出栈顶的字母;
- 若当前的字母和栈顶的字母不同,则放入当前的字母。
class Solution {
public String removeDuplicates(String S) {
int n=S.length();
if(n==1) return S;
String ans=""+S.charAt(0);
char temp=S.charAt(0);//记录栈顶
for(int i=1;i<n;i++){
if(ans.length()!=0&&S.charAt(i)==ans.charAt(ans.length()-1)) {//如果与栈顶字符一致,则弹出栈顶,并更新栈顶
ans=ans.substring(0,ans.length()-1);//去掉字符串的最后一个字符,即弹出栈顶
}
else{//如果与栈顶字符不一致,则入栈,并更新栈顶
ans+=S.charAt(i);
}
}
return ans;
}
}
执行用时:228 ms, 在所有 Java 提交中击败了8.55%的用户
内存消耗:40.5 MB, 在所有 Java 提交中击败了36.77%的用户
官解:
class Solution {
public String removeDuplicates(String S) {
StringBuilder sb = new StringBuilder();
int sbLength = 0;
for (char character : S.toCharArray()) {
if (sbLength != 0 && character == sb.charAt(sbLength - 1))//如果与栈顶的字符一致
sb.deleteCharAt(sbLength-- - 1);//弹出该栈顶
else {//如果与栈顶字符不一致
sb.append(character);//入栈
sbLength++;
}
}
return sb.toString();
}
}
执行用时:10 ms, 在所有 Java 提交中击败了93.19%的用户
内存消耗:40 MB, 在所有 Java 提交中击败了98.06%的用户
复杂度分析
- 时间复杂度:O(N),其中 NN 是字符串的长度。
- 空间复杂度:O(N)。
2、#682棒球比赛(类似计算器)
(1)、题目
难度:简单
你现在是棒球比赛记录员。
给定一个字符串列表,每个字符串可以是以下四种类型之一:
1.整数(一轮的得分):直接表示您在本轮中获得的积分数。
- “+”(一轮的得分):表示本轮获得的得分是前两轮有效 回合得分的总和。
- “D”(一轮的得分):表示本轮获得的得分是前一轮有效 回合得分的两倍。
- “C”(一个操作,这不是一个回合的分数):表示您获得的最后一个有效 回合的分数是无效的,应该被移除。
每一轮的操作都是永久性的,可能会对前一轮和后一轮产生影响。
你需要返回你在所有回合中得分的总和。
示例 1:
输入: [“5”,“2”,“C”,“D”,"+"]
输出: 30
解释:
第1轮:你可以得到5分。总和是:5。
第2轮:你可以得到2分。总和是:7。
操作1:第2轮的数据无效。总和是:5。
第3轮:你可以得到10分(第2轮的数据已被删除)。总数是:15。
第4轮:你可以得到5 + 10 = 15分。总数是:30。
示例 2:
输入: [“5”,"-2",“4”,“C”,“D”,“9”,"+","+"]
输出: 27
解释:
第1轮:你可以得到5分。总和是:5。
第2轮:你可以得到-2分。总数是:3。
第3轮:你可以得到4分。总和是:7。
操作1:第3轮的数据无效。总数是:3。
第4轮:你可以得到-4分(第三轮的数据已被删除)。总和是:-1。
第5轮:你可以得到9分。总数是:8。
第6轮:你可以得到-4 + 9 = 5分。总数是13。
第7轮:你可以得到9 + 5 = 14分。总数是27。
注意:
输入列表的大小将介于1和1000之间。
列表中的每个整数都将介于-30000和30000之间。
(2)、解题
栈
让我们在处理数据时保持栈上每个有效回合的值。栈是理想的,因为我们只处理涉及最后或倒数第二轮的操作。
class Solution {
public int calPoints(String[] ops) {
Stack<Integer> stack=new Stack();
int sum=0;
for(String op:ops){
if(op.equals("+")){
int top1=stack.pop();//弹出栈顶值,并返回该值,不弹出该值,取不到栈顶下面的值
int top2=stack.peek();//只是返回栈顶的值,并不弹出
int top=top1+top2;//新栈顶
stack.push(top1);//把被弹出的top1压回去
stack.push(top);//新栈顶入栈
sum+=top;
}
else if(op.equals("D")){
int top=stack.peek();//返回栈顶值,并不弹出
stack.push(top*2);//压入栈
sum+=top*2;
}
else if(op.equals("C")){
int top=stack.pop();//将栈顶弹出
sum-=top;
}else{//将数字都压入栈。因为示例中除了三种符号和数字,并无其他,就不考虑其他了
stack.push(Integer.valueOf(op));
sum+=Integer.valueOf(op);
}
}
return sum;
}
}
执行用时:3 ms, 在所有 Java 提交中击败了85.60%的用户
内存消耗:39.2 MB, 在所有 Java 提交中击败了32.00%的用户
复杂度分析
复杂度分析:O(N),其中 NN是 ops 的长度。我们解析给定数组中的每个元素,然后每个元素执行O(1) 的工作。
空间复杂度:O(N),用于存储 stack 的空间。