目录
基本计算器II(medium)
题目解析
1.题目链接:. - 力扣(LeetCode)
2.题目描述
给你⼀个字符串表达式s,请你实现⼀个基本计算器来计算并返回它的值。整数除法仅保留整数部分。
你可以假设给定的表达式总是有效的。所有中间结果将在[-2^31,2^31-1]的范围内。注意:不允许使⽤任何将字符串作为数学表达式计算的内置函数,⽐如eval()。
⽰例1:
输⼊:s="3+2*2"输出:7
⽰例2:
输⼊:s="3/2"输出:1
⽰例3:
输⼊:s="3+5/2"输出:5
提⽰:• 1<=s.length<=3*10^5• s由整数和算符('+','-','*','/')组成,中间由⼀些空格隔开• s表⽰⼀个有效表达式
• 表达式中的所有整数都是⾮负整数,且在范围[0,2^31-1]内• 题⽬数据保证答案是⼀个32-bit整数
题⽬解析:
⼀定要认真看题⽬的提⽰,从提⽰中我们可以看到这道题:• 只有「加减乘除」四个运算;
• 没有括号;
• 并且每⼀个数都是⼤于等于 0 的;
这样可以⼤⼤的「减少」我们需要处理的情况。
讲解算法原理
解法(栈):
算法思路:
由于表达式⾥⾯没有括号,因此我们只⽤处理「加减乘除」混合运算即可。根据四则运算的顺序,我们可以先计算乘除法,然后再计算加减法。由此,我们可以得出下⾯的结论:
• 当⼀个数前⾯是 '+' 号的时候,这⼀个数是否会被⽴即计算是「不确定」的,因此我们可以先压
⼊栈中;
• 当⼀个数前⾯是 '-' 号的时候,这⼀个数是否被⽴即计算也是「不确定」的,但是这个数已经
和前⾯的-号绑定了,因此我们可以将这个数的相反数压⼊栈中;
• 当⼀个数前⾯是 '*' 号的时候,这⼀个数可以⽴即与前⾯的⼀个数相乘,此时我们让将栈顶的元
素乘上这个数;
• 当⼀个数前⾯是 '/' 号的时候,这⼀个数也是可以⽴即被计算的,因此我们让栈顶元素除以这个
数。
当遍历完全部的表达式的时候,栈中剩余的「元素之和」就是最终结果。
编写代码
c++算法代码:
class Solution
{
public:
int calculate(string s)
{
vector<int> st; // ⽤数组来模拟栈结构
int i = 0, n = s.size();
char op = '+';
while(i < n)
{
if(s[i] == ' ') i++;
else if(s[i] >= '0' && s[i] <= '9')
{
// 先把这个数字给提取出来
int tmp = 0;
while(i < n && s[i] >= '0' && s[i] <= '9')
tmp = tmp * 10 + (s[i++] - '0');
if(op == '+') st.push_back(tmp);
else if(op == '-') st.push_back(-tmp);
else if(op == '*') st.back() *= tmp;
else st.back() /= tmp;
}
else
{
op = s[i];
i++;
}
}
int ret = 0;
for(auto x : st) ret += x;
return ret;
}
};
java算法代码:
class Solution
{
public int calculate(String _s)
{
Deque<Integer> st = new ArrayDeque<>();
char op = '+';
int i = 0, n = _s.length();
char[] s = _s.toCharArray();
while(i < n)
{
if(s[i] == ' ') i++;
else if(s[i] >= '0' && s[i] <= '9')
{
int tmp = 0;
while(i < n && s[i] >= '0' && s[i] <= '9')
{
tmp = tmp * 10 + (s[i] - '0');
i++;
}
if(op == '+') st.push(tmp);
else if(op == '-') st.push(-tmp);
else if(op == '*') st.push(st.pop() * tmp);
else st.push(st.pop() / tmp);
}
else
{
op = s[i];
i++;
}
}
// 统计结果
int ret = 0;
while(!st.isEmpty())
{
ret += st.pop();
}
return ret;
}
}
字符串解码(medium)
题目解析
1.题目链接:. - 力扣(LeetCode)
2.题目描述
给定⼀个经过编码的字符串,返回它解码后的字符串。
编码规则为:k[encoded_string],表⽰其中⽅括号内部的encoded_string正好重复k次。注意k保证为正整数。
你可以认为输⼊字符串总是有效的;输⼊字符串中没有额外的空格,且输⼊的⽅括号总是符合格式要求的。
此外,你可以认为原始数据不包含数字,所有的数字只表⽰重复的次数k,例如不会出现像3a或2[4]的输⼊。
⽰例1:
输⼊:s="3[a]2[bc]"
输出:"aaabcbc"
⽰例2:
输⼊:s="3[a2[c]]"
输出:"accaccacc"
⽰例3:
输⼊:s="2[abc]3[cd]ef"
输出:"abcabccdcdcdef"
讲解算法原理
解法(两个栈):
算法思路:
对于 3[ab2[cd]] ,我们需要先解码内部的,再解码外部(为了⽅便区分,使⽤了空格):• 3[ab2[cd]] -> 3[abcd cd] -> abcdcd abcdcd abcdcd
在解码 cd 的时候,我们需要保存 3 ab 2 这些元素的信息,并且这些信息使⽤的顺序是从后往前,正好符合栈的结构,因此我们可以定义两个栈结构,⼀个⽤来保存解码前的重复次数 k (左括号前的数字),⼀个⽤来保存解码之前字符串的信息(左括号前的字符串信息)。
编写代码
c++算法代码:
class Solution
{
public:
string decodeString(string s)
{
stack<int> nums;
stack<string> st;
st.push("");
int i = 0, n = s.size();
while(i < n)
{
if(s[i] >= '0' && s[i] <= '9')
{
int tmp = 0;
while(s[i] >= '0' && s[i] <= '9')
{
tmp = tmp * 10 + (s[i] - '0');
i++;
}
nums.push(tmp);
}
else if(s[i] == '[')
{
i++; // 把括号后⾯的字符串提取出来
string tmp = "";
while(s[i] >= 'a' && s[i] <= 'z')
{
tmp += s[i];
i++;
}
st.push(tmp);
}
else if(s[i] == ']')
{
string tmp = st.top();
st.pop();
int k = nums.top();
nums.pop();
while(k--)
{
st.top() += tmp;
}
i++; // 跳过这个右括号
}
else
{
string tmp;
while(i < n && s[i] >= 'a' && s[i] <= 'z')
{
tmp += s[i];
i++;
}
st.top() += tmp;
}
}
return st.top();
}
};
java算法代码:
class Solution
{
public String decodeString(String _s)
{
Stack<StringBuffer> st = new Stack<>();
st.push(new StringBuffer()); // 先放⼀个空串进去 Stack<Integer> nums = new Stack<>();
int i = 0, n = _s.length();
char[] s = _s.toCharArray();
while(i < n)
{
if(s[i] >= '0' && s[i] <= '9')
{
int tmp = 0;
while(i < n && s[i] >= '0' && s[i] <= '9')
{
tmp = tmp * 10 + (s[i] - '0');
i++;
}
nums.push(tmp);
}
else if(s[i] == '[')
{
i++; // 把后⾯的字符串提取出来
StringBuffer tmp = new StringBuffer();
while(i < n && s[i] >= 'a' && s[i] <= 'z')
{
tmp.append(s[i]);
i++;
}
st.push(tmp);
}
else if(s[i] == ']')
{
// 解析
StringBuffer tmp = st.pop();
int k = nums.pop();
while(k-- != 0)
{
st.peek().append(tmp);
}
i++;
}
else
{
StringBuffer tmp = new StringBuffer();
while(i < n && s[i] >= 'a' && s[i] <= 'z')
{
tmp.append(s[i]);
i++;
}
st.peek().append(tmp);
}
}
return st.peek().toString();
}
}