1.224. 基本计算器 - 力扣(LeetCode)
这道题的特点就是它的运算符只有加和减 那么就可以通过改变数字的正负符号来代表操作加减
因为减去一个数,就是加上这个数的相反数
这个栈不是用来存放数的,而是用来存放操作符号的。代表是加还是减。用flag来代表一个操作。
flag = 1 时是操作+,flag = -1 时是操作-。这里的flag更可以看作一个乘法因子,+操作就是使这个数是一个正数,-操作就是使这个数变为一个负数。那么1就表示这个数按原值累加到结果res, -1表示这个数取它的相反数累加到结果。
要将栈初始化为1,可以把题目看作
(+1(+4+5+2)-3)+6+8)
遇到空格的时候就直接跳过
遇到 "(" 就将 flag = 1入栈,代表有一个操作要进行,默认操作为+,因为后面遇到 - 还会重新赋值
遇到 ")" 就 弹出栈顶元素,代表"( )" 中的这个操作已经完成了
遇到 ”+“ 将flag设为1,遇到 ”-“ 将flag设为-1
遇到数字,用一个while循环来取得这个数字
long num = 0; //怕溢出
while(i<n && s[i] <= '0' && s[i] >= '9'){
num = num * 10 + s[i] - '0';
}
然后就可以累加res了。
res += num * flag; // 哎哟 我觉得这个也神奇
class Solution {
public:
int calculate(string s) {
stack<int> st;
st.push(1);
int res = 0, flag = 1, n = s.size(), i = 0;
while(i < n){
if(s[i] == ' ')
i++;
else if(s[i] == '('){
st.push(1);
i++;
}
else if(s[i] == ')'){
st.pop();
i++;
}
else if(s[i] == '+'){
flag = st.top();
i++;
}
else if(s[i] == '-'){
flag = -st.top();
i++;
}
else{
long num = 0;
while(i < n && s[i] >= '0' && s[i] <= '9'){
num = num * 10 + s[i] - '0';
i++;
}
res += num * flag;
}
}
return res;
}
};
其实我感觉这个是不是降低了难度,因为它只有加减同级运算。
2. 227. 基本计算器 II - 力扣(LeetCode)
注意:● 用一个数组来模拟栈,它的本质还是先进后出,不过更加方便操作
● 由于乘除的优先级高于加减所以遇到乘除的时候就直接操作,遇到加减先入栈,最后累加
● 用一个变量pre记录上一个字符,在遇到新的数字的时候,根据这个字符来确定怎么处理 当前数字num与上一个数字(栈顶元素
如果此时遍历的字符是数字,那么就想办法取出这个数字
如果此时遍历到的不是数字,并且也不为空 或者是 遍历到最后一个字符了,那么就看pre:
是+:将这个数按原值放入栈中
是-:直接改变这个数字将这个数乘上负号,变为其相反数
是 * 或 / :直接将栈顶的数字(上次的数字)和num(这次也就是后一次取得的数字) 进行操作。
然后迭代更新pre,将num重设为0,下次重新取
最后就是累加栈中的数字辣,可以类比一下上一题都是通过这个数字的符号来代表它们的加减操作
class Solution {
public:
int calculate(string s) {
vector<int> st;
char pre = '+';
for(int i = 0; i < s.size(); i++){
if(isdigit(s[i]){
num = num * 10 + s[i] - '0';
}
if(!isdigit(s[i]) && s[i] != ' ' || i == n-1){
switch(pre){
case '+':
st.push_back(num);
break;
case '-':
st.push_back(-num);
break;
case '*':
st.back *= num;
break;
default:
st.back() /= num;
}
pre = s[i];
num = 0;
}
}
return accumulate(st.begin(), st.end(), 0);
}
};
做的时候,发现自己基础真的是不牢固啊。。。。
- 第一个 if 不能改成 else if:
第一个 if 是结合 for 循环,取数的一个过程,如果num这个数是一个跨字符的多位数,它也可以完整的取出来
如果是第二个字符是 if 每个字符就是独立判断,两个if语句都会进去试一下,如果是else if,意味着只有当当前字符是数字,后续的逻辑才会执行(才会去switch) - 不要忘记最后一个数字,如果不加 i == n -1的话,就不会进行最后一个运算符的操作
- accumulate( )函数
accumulate(st.begin(), st.end(), 0);
参数1:累加范围的起始值 参数2:累加范围的终止 参数3:累加值得初始值
感觉这个pre用的好巧妙啊啊啊啊啊。。。。
3.682. 棒球比赛 - 力扣(LeetCode)
做完上面两道感觉这个的确是简单啊,但是还存在问题。。。
class Solution {
public:
int calPoints(vector<string>& operations) {
vector<int> st;
int n = operations.size();
for(int i = 0; i < n; i++){
if(operations[i] == "C"){
st.pop_back();
}
else if(operations[i] == "D"){
st.push_back(st.back() * 2);
}
else if(operations[i] == "+"){
// if(st.size() >=2 ){
int temp = st[st.size() - 1] + st[st.size() - 2];
st.push_back(temp);
// }
}
else{
st.push_back(stoi(operations[i]));
}
}
return accumulate(st.begin(), st.end(), 0);
}
};
就先别判断数字,然后有什么做什么,注意清楚题目所要求的逻辑
最后遍历累加好
4.71. 简化路径 - 力扣(LeetCode)
这个也挺有意思的我觉得。
上周什么时候写的没发呢