文章目录
- 一、删除字符串中的所有相邻重复项
- [二、基本计算器 II](#二、基本计算器 II)
- 三、字符串解码
- 四、验证栈序列
一、删除字符串中的所有相邻重复项
给出由小写字母组成的字符串 s,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
在 s 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
解题思路
- 读到这种题就要意识到与栈这种数据结构特性的相似性
- 将每个字符依次入栈,每次与栈顶元素进行比较,相同的话就要删掉栈顶元素,接着往后遍历。我们可以使用数组、或者在本题中可以使用StringBuilder来模拟栈。
代码实现及解析
java
class Solution {
public String removeDuplicates(String s) {
StringBuilder str=new StringBuilder();//模拟一个栈
for(char ch:s.toCharArray()){
if(str.length()>0&&ch==str.charAt(str.length()-1)){//如果当前遍历元素与str末尾(栈顶)元素相等,就删掉栈顶元素
str.deleteCharAt(str.length()-1);
}else{
str.append(ch);
}
}
return str.toString();
}
}
总结
栈的性质的应用,复习解题思路
二、基本计算器 II
给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。
整数除法仅保留整数部分。
你可以假设给定的表达式总是有效的。所有中间结果将在 [-231, 231 - 1] 的范围内。
注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval() 。
提示:
1 <= s.length <= 3 * 105
s 由整数和算符 ('+', '-', '*', '/') 组成,
中间由一些空格隔开s 表示一个 有效表达式
表达式中的所有整数都是非负整数,且在范围 [0, 231 - 1] 内
题目数据保证答案是一个 32-bit 整数
示例 :
输入:s = "3+2*2"
输出:7
解题思路
-
这类"表达式求值"题目都是使用栈来解答 -
对于'+'、'---'后面的数字我们不能直接运算,因为不知道它们后面的数字是否还连着'*'、'/' 运算符,
所以我们应该先处理乘除运算,最后再计算加减。我们先定义一个变量op记录最新更新的运算符是什么,判断遍历到的数字num的前面的运算符(也就是最新更新的运算符op)是什么来处理该数字并将其入栈,op是'+'就直接将其入栈,是'---'就取相反数入栈,是'*'、'/'运算符就取栈顶元素与num运算并将结果入栈。 -
最后只需将栈中元素全部加和就可得出正确结果
-
没有括号,所以我们不需要处理括号问题,并且每一个数都是大于等于0的
代码实现及解析
java
class Solution {
public int calculate(String s) {
char[] str=s.toCharArray();
Stack<Integer> stack=new Stack<>();//最终储存在Stack中的就是在处理完乘、除法之后的所有数
char op='+';//op单独记录最近一次更新的运算符(初始化为'+')
int i=0;
while(i<str.length){
if(str[i]==' '){//千万不要忘记处理空格字符
i++;
}else if(str[i]>='0'&&str[i]<='9'){//数字
int num=0;
while(i<str.length&&str[i]>='0'&&str[i]<='9'){//将连续的数学字符处理为完整的数学自然数
num*=10;
num+=str[i]-'0';
i++;
}
//开始判断上一次最新更新的op的类型,并根据op对num进行处理
if(op=='+'){
stack.push(num);
}else if(op=='-'){
stack.push(-num);//这样最终可以对栈中元素直接进行加和
}else if(op=='*'){
stack.push(stack.pop()*num);
}else{
stack.push(stack.pop()/num);
}
}else{
op=str[i++];//更新操作符
}
}
//最后就可以把栈中的数全部加和
int sum=0;
while(!stack.empty()){
sum+=stack.pop();
}
return sum;
}
}
总结
复习解题思路
三、字符串解码
给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。
你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。
此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。
示例 1:
输入:s = "3[a]2[bc]"
输出:"aaabcbc"
示例 2:
输入:s = "3[a2[c]]"
输出:"accaccacc"
代码实现解析
java
class Solution {
public String decodeString(String s) {
char[] str=s.toCharArray();
Stack<StringBuilder> stringStack=new Stack<>();
stringStack.push(new StringBuilder());//提前入栈一个空字符串,否则第一次解析的字符串没地方拼接
Stack<Integer> numsStack=new Stack<>();
int i=0;
while(i<str.length){//遍历字符串
if(str[i]>='0'&&str[i]<='9'){//是数字
int tmpNum=0;
while(str[i]>='0'&&str[i]<='9'){//把数字提取出来
tmpNum*=10;
tmpNum+=str[i++]-'0';
}//i到'['位置,循环结束
numsStack.push(tmpNum);//将数字入栈
//下面开始把'['后面的字符串提取出来
i++;
StringBuilder tmpStr=new StringBuilder();
while(str[i]>='a'&&str[i]<='z'){
tmpStr.append(str[i++]);
}
stringStack.push(tmpStr);//将暂时未解析的字符串先单独入栈,下次需要处理直接pop()
//循环结束后还不知道此时i位置是什么字符,可能是']',也可能嵌套了编码字符串,那i位置就是会是数字字符
}else if(str[i]==']'){
//遇到了']',开始解析
int k=numsStack.pop();
StringBuilder tmp=stringStack.pop();
for(int j=0;j<k;j++){//用j别与上面的i冲突了
stringStack.peek().append(tmp);//将解析后的的字符串直接追加到栈顶字符串后面(与未解析的处理方式就不一样)
}
i++;//往后遍历
}else{//若单独遇见字符(串)(也就是不在'[]'里面)
while(i<str.length&&str[i]>='a'&&str[i]<='z'){//这个操作可就要注意i可能会越界了
stringStack.peek().append(str[i++]);//这样的直接在处理过的字符串(栈顶)后面追加
}
}
}
return stringStack.pop().toString();
}
}
总结
解题思路复习代码自己再琢磨一遍要找到由括号界定的数据处理规则、分情况讨论,比如本题:未解析的字符串要单独入栈,下次需要解析了直接pop。而解析过的字符串要追加( append() )到字符串栈的栈顶字符串的后面,因为解析过的本来就要追加到结果的后面,而假如整体还需要被解析,那么也正好是要追加到后面再解析的。
四、验证栈序列
给定 pushed 和 popped 两个序列,每个序列中的 值都不重复,只有当它们可能是在最初空栈上进行的推入 push 和弹出 pop 操作序列的结果时,返回 true;否则,返回 false 。
解题思路
- 这种选择题考的也多,其实就是把做选择题的过程模拟一遍。
- 再把pushed数组入栈的过程中与poped数组对比,看是否可以出栈,最后如果正常匹配的话栈中的元素应该都被pop()出去了,栈为空。
代码实现及解析
java
class Solution {
public boolean validateStackSequences(int[] pushed, int[] popped) {
Stack<Integer> stack=new Stack<>();
int j=0;
for(int i=0;i<pushed.length;i++){
stack.push(pushed[i]);//入栈
while(!stack.empty()&&stack.peek()==popped[j]){//入栈后就要检查是否可以出栈
stack.pop();
j++;
}
}
if(stack.empty()) return true;//正常情况如果匹配的话stack中就不应该还留有元素
else return false;
}
}
总结
入栈和出栈序列匹配问题