给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 ‘.’ 和 ‘*’ 的正则表达式匹配。
‘.’ 匹配任意单个字符
‘*’ 匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。
说明:
s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和 *。
示例 1:
输入:
s = “aa”
p = “a”
输出: false
解释: “a” 无法匹配 “aa” 整个字符串。
示例 2:
输入:
s = “aa”
p = “a*”
输出: true
解释: 因为 ‘*’ 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 ‘a’。因此,字符串 “aa” 可被视为 ‘a’ 重复了一次。
示例 3:
输入:
s = “ab”
p = “."
输出: true
解释: ".” 表示可匹配零个或多个(’*’)任意字符(’.’)。
示例 4:
输入:
s = “aab”
p = “cab”
输出: true
解释: 因为 ‘*’ 表示零个或多个,这里 ‘c’ 为 0 个, ‘a’ 被重复一次。因此可以匹配字符串 “aab”。
示例 5:
输入:
s = “mississippi”
p = “misisp*.”
输出: false
链接:https://leetcode-cn.com/problems/regular-expression-matching
【思路】先从基本的递归考虑,然后再优化到动态规划。
【代码1:基本递归】这种解法复杂度很高,只是为了更好的理解DP解法。
public bool IsMatch(string text, string pattern) {
if (string.IsNullOrEmpty(pattern)) return string.IsNullOrEmpty(text);
//先看第一个字符能不能匹配上
var first_match = (!string.IsNullOrEmpty(text) &&
(pattern[0] == text[0] || pattern[0] == '.'));
//如果pattern的长度大于2而且第二个字符是*号
if (pattern.Length >= 2 && pattern[1] == '*'){
//*代表零个前一个字符时直接看text和substring(2)是否匹配
return (IsMatch(text, pattern.Substring(2)) ||
//*代表一个或多个前一个字符时,且第一个字符匹配上了,去掉text第一个字符直接跟pattern比较
(first_match && IsMatch(text.Substring(1), pattern)));
} else {
//如果pattern第二个字符不是*号,那么就同时看第一个字符是否匹配上,且去掉他们两个第一个字符再看是否匹配
return first_match && IsMatch(text.Substring(1), pattern.Substring(1));
}
}
【代码2:动态规划】时间复杂度为 O(TP),空间复杂度为O(TP)
public bool IsMatch(string text, string pattern) {
var dp = new bool[text.Length + 1, pattern.Length + 1];
dp[text.Length, pattern.Length] = true;
for (int i = text.Length; i >= 0; i--){
for (int j = pattern.Length - 1; j >= 0; j--){
var first_match = (i < text.Length &&
(pattern[j] == text[i] ||
pattern[j] == '.'));
if (j + 1 < pattern.Length && pattern[j+1] == '*'){
dp[i, j] = dp[i, j+2] || first_match && dp[i+1, j];
} else {
dp[i, j] = first_match && dp[i+1, j+1];
}
}
}
return dp[0, 0];
}
给定一个字符串 (s) 和一个字符模式 § ,实现一个支持 ‘?’ 和 ‘*’ 的通配符匹配。
‘?’ 可以匹配任何单个字符。
‘*’ 可以匹配任意字符串(包括空字符串)。//注意此处和前一个题不太一样
两个字符串完全匹配才算匹配成功。
说明:
s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母,以及字符 ? 和 *。
示例 1:
输入:
s = “aa”
p = “a”
输出: false
解释: “a” 无法匹配 “aa” 整个字符串。
示例 2:
输入:
s = “aa”
p = “*”
输出: true
解释: ‘*’ 可以匹配任意字符串。
示例 3:
输入:
s = “cb”
p = “?a”
输出: false
解释: ‘?’ 可以匹配 ‘c’, 但第二个 ‘a’ 无法匹配 ‘b’。
示例 4:
输入:
s = “adceb”
p = “*a*b”
输出: true
解释: 第一个 ‘*’ 可以匹配空字符串, 第二个 ‘*’ 可以匹配字符串 “dce”.
示例 5:
输入:
s = “acdcb”
p = “a*c?b”
输入: false
链接:https://leetcode-cn.com/problems/wildcard-matching
public bool IsMatch(string s, string p) {
int m = s.Length, n = p.Length;
var f = new bool[m + 1, n + 1];
f[0, 0] = true;
for(int i = 1; i <= n; i++){
f[0, i] = f[0, i - 1] && p[i - 1] == '*';
}
//注意此处从1到结尾,所以i-1对应dp中的i,j-1对应dp中的j
for(int i = 1; i <= m; i++){
for(int j = 1; j <= n; j++){
if(s[i - 1] == p[j - 1] || p[j - 1] == '?'){
f[i, j] = f[i - 1, j - 1];
}
if(p[j - 1] == '*'){
f[i, j] = f[i, j - 1] || f[i - 1, j];
}
}
}
return f[m, n];
}
请你来实现一个 atoi 函数,使其能将字符串转换成整数。
首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。
当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。
该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。
注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。
在任何情况下,若函数不能进行有效的转换时,请返回 0。
说明:
假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231, 231 − 1]。如果数值超过这个范围,请返回 INT_MAX (231 − 1) 或 INT_MIN (−231) 。
示例 1:
输入: “42”
输出: 42
示例 2:
输入: " -42"
输出: -42
解释: 第一个非空白字符为 ‘-’, 它是一个负号。
我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。
示例 3:
输入: “4193 with words”
输出: 4193
解释: 转换截止于数字 ‘3’ ,因为它的下一个字符不为数字。
示例 4:
输入: “words and 987”
输出: 0
解释: 第一个非空字符是 ‘w’, 但它不是数字或正、负号。
因此无法执行有效的转换。
示例 5:
输入: “-91283472332”
输出: -2147483648
解释: 数字 “-91283472332” 超过 32 位有符号整数范围。
因此返回 INT_MIN (−231) 。
链接:https://leetcode-cn.com/problems/string-to-integer-atoi
public int MyAtoi(string str) {
var sign = 1; var bas = 0; var i = 0;//bas=base
//1. Trim + 判断null
str = str.Trim();
if(string.IsNullOrEmpty(str)) return 0;
//2. 记录Sign
if (str[i] == '-' || str[i] == '+') {
sign = str[i] == '-'?-1:1;
i++;
}
while (i<str.Length && str[i] >= '0' && str[i] <= '9') {
//3.还没加上新来的字符是就已经比max/10大了,加上新来的就一定会溢出
//4.没加上新来的字符时刚好等于max/10,如果新来的大于等于8,正数会溢出,负数如果大于8溢出,但最后反正正数溢出按max,负数溢出按min,所以刚好
if (bas > int.MaxValue / 10 || (bas == int.MaxValue / 10 && str[i] - '0' >= 8)) {
return sign == 1? int.MaxValue : int.MinValue;
}
bas = 10 * bas + (str[i++] - '0');
}
return bas * sign;
}
实现一个基本的计算器来计算一个简单的字符串表达式的值。
字符串表达式可以包含左括号 ( ,右括号 ),加号 + ,减号 -,非负整数和空格 。
示例 1:
输入: “1 + 1”
输出: 2
示例 2:
输入: " 2-1 + 2 "
输出: 3
示例 3:
输入: “(1+(4+5+2)-3)+(6+8)”
输出: 23
说明:
你可以假设所给定的表达式都是有效的。
请不要使用内置的库函数 eval。
链接:https://leetcode-cn.com/problems/basic-calculator
public int Calculate(string s) {
var nums = new Stack<int>();
var ops = new Stack<int>();
int num = 0;
int rst = 0;
int sign = 1;
foreach (char c in s) {
if(c==' ') continue;
else if (c>='0'&&c<='9') {
num = num * 10 + c - '0';
}
else {
rst += sign * num;
num = 0;
if (c == '+') sign = 1;
if (c == '-') sign = -1;
if (c == '(') {
nums.Push(rst);
ops.Push(sign);
rst = 0;
sign = 1;
}
if (c == ')' && ops.Count!=0) {
rst = ops.Pop() * rst + nums.Pop();
}
}
}
rst += sign * num;
return rst;
}
实现一个基本的计算器来计算一个简单的字符串表达式的值。
字符串表达式仅包含非负整数,+, - ,*,/ 四种运算符和空格 。 整数除法仅保留整数部分。
示例 1:
输入: “3+2*2”
输出: 7
示例 2:
输入: " 3/2 "
输出: 1
示例 3:
输入: " 3+5 / 2 "
输出: 5
说明:
你可以假设所给定的表达式都是有效的。
请不要使用内置的库函数 eval。
链接:https://leetcode-cn.com/problems/basic-calculator-ii
public int Calculate(string s) {
int len = s.Length;
if(s==null || len==0) return 0;
var stack = new Stack<int>();
int num = 0;
char sign = '+';
for(int i=0;i<len;i++){
if(char.IsDigit(s[i])){
num = num*10+s[i]-'0';
}
if((!char.IsDigit(s[i]) &&' '!=s[i]) || i==len-1){
if(sign=='-'){
stack.Push(-num);
}
if(sign=='+'){
stack.Push(num);
}
if(sign=='*'){
stack.Push(stack.Pop()*num);
}
if(sign=='/'){
stack.Push(stack.Pop()/num);
}
sign = s[i];
num = 0;
}
}
int re = 0;
foreach(int i in stack){
re += i;
}
return re;
}
实现一个基本的计算器来计算简单的表达式字符串。
表达式字符串可以包含左括号 ( 和右括号 ),加号 + 和减号 -,非负 整数和空格 。
表达式字符串只包含非负整数, +, -, *, / 操作符,左括号 ( ,右括号 )和空格 。整数除法需要向下截断。
你可以假定给定的字符串总是有效的。所有的中间结果的范围为 [-2147483648, 2147483647]。
一些例子:
“1 + 1” = 2
" 6-4 / 2 " = 4
“2*(5+52)/3+(6/2+8)" = 21
"(2+6 3+5- (3*14/7+2)*5)+3”=-12
注:不要 使用内置库函数 eval。
链接:https://leetcode-cn.com/problems/basic-calculator-iii
public class Solution {
public int Calculate(string s) {
var i = 0;
return ParseExpr(s, ref i);
}
private int ParseExpr(string s, ref int i){
var nums = new List<int>();
char op = '+';
int n = 0;
for (; i < s.Length && op != ')'; ++i) {
if (s[i] == ' ') {
continue;
}
if (s[i] == '(') {
i++;
n = ParseExpr(s, ref i);
}
else if (char.IsDigit(s[i])){
n = ParseNum(s, ref i);
}
switch(op) {
case '+':
nums.Add(n);
break;
case '-':
nums.Add(-n);
break;
case '*':
nums[nums.Count-1] *= n;
break;
case '/':
nums[nums.Count-1] /= n;
break;
}
if(i<s.Length) op = s[i];
}
int res = 0;
foreach (int num in nums) {
res += num;
}
return res;
}
private int ParseNum(string s, ref int i) { // parse the num
int n = 0;
while (i < s.Length && char.IsDigit(s[i])) {
n = 10 * n + s[i++] - '0';
}
return n;
}
}
根据逆波兰表示法,求表达式的值。
有效的运算符包括 +, -, *, / 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。
说明:
整数除法只保留整数部分。
给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。
示例 1:
输入: [“2”, “1”, “+”, “3”, “*”]
输出: 9
解释: ((2 + 1) * 3) = 9
示例 2:
输入: [“4”, “13”, “5”, “/”, “+”]
输出: 6
解释: (4 + (13 / 5)) = 6
示例 3:
输入: [“10”, “6”, “9”, “3”, “+”, “-11”, “", “/”, "”, “17”, “+”, “5”, “+”]
输出: 22
解释:
((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22
链接:https://leetcode-cn.com/problems/evaluate-reverse-polish-notation
public int EvalRPN(string[] tokens) {
int a,b;
var S = new Stack<int>();
foreach (var s in tokens) {
if(s=="+") {
S.Push(S.Pop()+S.Pop());
}
else if(s=="/") {
b = S.Pop();
a = S.Pop();
S.Push(a / b);
}
else if(s=="*") {
S.Push(S.Pop() * S.Pop());
}
else if(s=="-") {
b = S.Pop();
a = S.Pop();
S.Push(a - b);
}
else {
S.Push(int.Parse(s));
}
}
return S.Pop();
}
给定一个含有数字和运算符的字符串,为表达式添加括号,改变其运算优先级以求出不同的结果。你需要给出所有可能的组合的结果。有效的运算符号包含 +, - 以及 * 。
示例 1:
输入: “2-1-1”
输出: [0, 2]
解释:
((2-1)-1) = 0
(2-(1-1)) = 2
示例 2:
输入: “2*3-4*5”
输出: [-34, -14, -10, -10, 10]
解释:
(2*(3-(4*5))) = -34
((2*3)-(4*5)) = -14
((2*(3-4))*5) = -10
(2*((3-4)*5)) = -10
(((2*3)-4)*5) = 10
链接:https://leetcode-cn.com/problems/different-ways-to-add-parentheses
public class Solution {
public IList<int> DiffWaysToCompute(string input)
{
var result = new List<int>();
if (input == null || input.Length == 0)
{
return result;
}
for (var i = 0; i < input.Length; i++)
{
if (input[i] == '+' || input[i] == '-' || input[i] == '*')
{
var sub1 = input.Substring(0, i);
var sub2 = input.Substring(i + 1);
var list1 = DiffWaysToCompute(sub1);
var list2 = DiffWaysToCompute(sub2);
foreach(var l1 in list1)
{
foreach(var l2 in list2)
{
switch (input[i])
{
case '+':
result.Add(l1 + l2);
break;
case '-':
result.Add(l1 - l2);
break;
case '*':
result.Add(l1 * l2);
break;
}
}
}
}
}
if (result.Count == 0)
{
result.Add(int.Parse(input));
}
return result;
}
}
给定一个仅包含数字 0-9 的字符串和一个目标值,在数字之间添加二元运算符(不是一元)+、- 或 * ,返回所有能够得到目标值的表达式。
示例 1:
输入: num = “123”, target = 6
输出: [“1+2+3”, “123”]
示例 2:
输入: num = “232”, target = 8
输出: [“23+2", "2+32”]
示例 3:
输入: num = “105”, target = 5
输出: [“1*0+5”,“10-5”]
示例 4:
输入: num = “00”, target = 0
输出: [“0+0”, “0-0”, “0*0”]
示例 5:
输入: num = “3456237490”, target = 9191
输出: []
链接:https://leetcode-cn.com/problems/expression-add-operators
public class Solution {
public IList<string> AddOperators(string num, int target) {
var exprs = new List<string>();
var preval = 0;
var expr = new char[num.Length*2];
var len = 0;
Recurse(num, 0, 0, target, expr, len, preval, exprs);
return exprs;
}
public void Recurse(string num, int index, long val, int target, char[] expr, int len, long preval, IList<string> exprs )
{
if(index == num.Length) {
if (val == target) exprs.Add(new string(expr, 0, len));
return;
}
long op2 = 0;
int l = len;
if(index != 0) len++;
for(int i = index; i<num.Length; i++) {
op2 = op2 * 10 + num[i] - '0';
expr[len++] = num[i];
if (index == 0)
{
Recurse(num, i+1, op2, target, expr, len, op2, exprs);
}
else
{
expr[l] = '+';
Recurse(num, i+1, val + op2, target, expr, len, op2, exprs);
expr[l] = '-';
Recurse(num, i+1, val - op2, target, expr, len, -op2, exprs);
expr[l] = '*';
var val3 = val - preval + (preval * op2);
Recurse(num, i+1, val3, target, expr, len, preval*op2, exprs);
}
if (num[index] == '0') break;
}
return;
}
}
给定一个以字符串表示的任意嵌套的三元表达式,计算表达式的值。你可以假定给定的表达式始终都是有效的并且只包含数字 0-9, ?, :, T 和 F (T 和 F 分别表示真和假)。
注意:
给定的字符串长度 ≤ 10000。
所包含的数字都只有一位数。
条件表达式从右至左结合(和大多数程序设计语言类似)。
条件是 T 和 F其一,即条件永远不会是数字。
表达式的结果是数字 0-9, T 或者 F。
示例 1:
输入: “T?2:3”
输出: “2”
解释: 如果条件为真,结果为 2;否则,结果为 3。
示例 2:
输入: “F?1:T?4:5”
输出: “4”
解释: 条件表达式自右向左结合。使用括号的话,相当于:
"(F ? 1 : (T ? 4 : 5))" "(F ? 1 : (T ? 4 : 5))"
-> "(F ? 1 : 4)" 或者 -> "(T ? 4 : 5)"
-> "4" -> "4"
示例 3:
输入: “T?T?F:5:3”
输出: “F”
解释: 条件表达式自右向左结合。使用括号的话,相当于:
"(T ? (T ? F : 5) : 3)" "(T ? (T ? F : 5) : 3)"
-> "(T ? F : 3)" 或者 -> "(T ? F : 5)"
-> "F" -> "F"
链接:https://leetcode-cn.com/problems/ternary-expression-parser
给一个 C++ 程序,删除程序中的注释。这个程序source是一个数组,其中source[i]表示第i行源码。 这表示每行源码由\n分隔。
在 C++ 中有两种注释风格,行内注释和块注释。
字符串// 表示行注释,表示//和其右侧的其余字符应该被忽略。
字符串/* 表示一个块注释,它表示直到*/的下一个(非重叠)出现的所有字符都应该被忽略。(阅读顺序为从左到右)非重叠是指,字符串/*/并没有结束块注释,因为注释的结尾与开头相重叠。
第一个有效注释优先于其他注释:如果字符串//出现在块注释中会被忽略。 同样,如果字符串/*出现在行或块注释中也会被忽略。
如果一行在删除注释之后变为空字符串,那么不要输出该行。即,答案列表中的每个字符串都是非空的。
样例中没有控制字符,单引号或双引号字符。比如,source = “string s = “/* Not a comment. */”;” 不会出现在测试样例里。(此外,没有其他内容(如定义或宏)会干扰注释。)
我们保证每一个块注释最终都会被闭合, 所以在行或块注释之外的/*总是开始新的注释。
最后,隐式换行符可以通过块注释删除。 有关详细信息,请参阅下面的示例。
从源代码中删除注释后,需要以相同的格式返回源代码。
示例 1:
输入:
source = ["/*Test program /", “int main()”, "{ ", " // variable declaration ", “int a, b, c;”, "/ This is a test", " multiline ", " comment for “, " testing */”, “a = b + c;”, “}”]
示例代码可以编排成这样:
/*Test program /
int main()
{
// variable declaration
int a, b, c;
/ This is a test
multiline
comment for
testing */
a = b + c;
}
输出: [“int main()”,"{ “,” “,“int a, b, c;”,“a = b + c;”,”}"]
编排后:
int main()
{
int a, b, c;
a = b + c;
}
解释:
第 1 行和第 6-9 行的字符串 /* 表示块注释。第 4 行的字符串 // 表示行注释。
示例 2:
输入:
source = [“a/comment", “line”, "more_comment/b”]
输出: [“ab”]
解释: 原始的 source 字符串是 “a/comment\nline\nmore_comment/b”, 其中我们用粗体显示了换行符。删除注释后,隐含的换行符被删除,留下字符串 “ab” 用换行符分隔成数组时就是 [“ab”].
注意:
source的长度范围为[1, 100].
source[i]的长度范围为[0, 80].
每个块注释都会被闭合。
给定的源码中不会有单引号、双引号或其他控制字符。
链接:https://leetcode-cn.com/problems/remove-comments
public IList<string> RemoveComments(string[] source) {
var inBlock = false;
var newline = new StringBuilder();
var ans = new List<String>();
foreach (string line in source) {
int i = 0;
char[] chars = line.ToCharArray();
if (!inBlock) newline = new StringBuilder();
while (i < line.Length) {
if (!inBlock && i+1 < line.Length && chars[i] == '/' && chars[i+1] == '*') {
inBlock = true;
i++;
} else if (inBlock && i+1 < line.Length && chars[i] == '*' && chars[i+1] == '/') {
inBlock = false;
i++;
} else if (!inBlock && i+1 < line.Length && chars[i] == '/' && chars[i+1] == '/') {
break;
} else if (!inBlock) {
newline.Append(chars[i]);
}
i++;
}
if (!inBlock && newline.Length > 0) {
ans.Add(newline.ToString());
}
}
return ans;
}
给定一个用字符串表示的整数的嵌套列表,实现一个解析它的语法分析器。
列表中的每个元素只可能是整数或整数嵌套列表
提示:你可以假定这些字符串都是格式良好的:
字符串非空
字符串不包含空格
字符串只包含数字0-9, [, - , ]
示例 1:
给定 s = “324”,
你应该返回一个 NestedInteger 对象,其中只包含整数值 324。
示例 2:
给定 s = “[123,[456,[789]]]”,
返回一个 NestedInteger 对象包含一个有两个元素的嵌套列表:
链接:https://leetcode-cn.com/problems/mini-parser
给定一个类似 Lisp 语句的表达式 expression,求出其计算结果。
表达式语法如下所示:
表达式可以为整数,let 语法,add 语法,mult 语法。表达式的结果总是一个整数。
(整数可以是正整数、负整数、0)
let 语法表示为 (let v1 e1 v2 e2 … vn en expr), 其中 let语法总是以字符串 "let"来表示,接下来会跟随一个或多个交替变量或表达式,也就是说,第一个变量 v1被分配为表达式 e1 的值,第二个变量 v2 被分配为表达式 e2 的值,以此类推;最终 let 语法的值为 expr表达式的值。
add语法表示为 (add e1 e2),其中 add 语法总是以字符串 "add"来表示,该语法总是有两个表达式e1、e2, 该语法的最终结果是 e1 表达式的值与 e2 表达式的值之和。
mult语法表示为 (mult e1 e2) ,其中 mult 语法总是以字符串"mult"表示, 该语法总是有两个表达式 e1、e2,该语法的最终结果是 e1 表达式的值与 e2 表达式的值之积。
在该题目中,变量的命名以小写字符开始,之后跟随0个或多个小写字符或数字。为了方便,“add”,“let”,“mult"会被定义为"关键字”,不会在表达式的变量命名中出现。
最后,要说一下范围的概念。在做计算时,需要注意优先级,在最内层(根据括号)的表达式的值应该先计算,然后依次计算外层的表达式。我们将保证每一个测试的表达式都是合法的。有关范围的更多详细信息,请参阅示例。
示例:
输入: (add 1 2)
输出: 3
输入: (mult 3 (add 2 3))
输出: 15
输入: (let x 2 (mult x 5))
输出: 10
输入: (let x 2 (mult x (let x 3 y 4 (add x y))))
输出: 14
解释:
表达式 (add x y), 在获取 x 值时, 我们应当由最内层依次向外计算, 首先遇到了 x=3, 所以此处的 x 值是 3.
输入: (let x 3 x 2 x)
输出: 2
解释: let 语句中的赋值运算按顺序处理即可
输入: (let x 1 y 2 x (add x y) (add x y))
输出: 5
解释:
第一个 (add x y) 计算结果是 3,并且将此值赋给了 x 。
第二个 (add x y) 计算结果就是 3+2 = 5 。
输入: (let x 2 (add (let x 3 (let x 4 x)) x))
输出: 6
解释:
(let x 4 x) 中的 x 的作用范围仅在()之内。所以最终做加法操作时,x 的值是 2 。
输入: (let a1 3 b2 (add a1 1) b2)
输出: 4
解释:
变量命名时可以在第一个小写字母后跟随数字.
注意:
我们给定的 expression 表达式都是格式化后的:表达式前后没有多余的空格,表达式的不同部分(关键字、变量、表达式)之间仅使用一个空格分割,并且在相邻括号之间也没有空格。我们给定的表达式均为合法的且最终结果为整数。
我们给定的表达式长度最多为 2000 (表达式也不会为空,因为那不是一个合法的表达式)。
最终的结果和中间的计算结果都将是一个 32 位整数。
链接:https://leetcode-cn.com/problems/parse-lisp-expression
给定一个化学式formula(作为字符串),返回每种原子的数量。
原子总是以一个大写字母开始,接着跟随0个或任意个小写字母,表示原子的名字。
如果数量大于 1,原子后会跟着数字表示原子的数量。如果数量等于 1 则不会跟数字。例如,H2O 和 H2O2 是可行的,但 H1O2 这个表达是不可行的。
两个化学式连在一起是新的化学式。例如 H2O2He3Mg4 也是化学式。
一个括号中的化学式和数字(可选择性添加)也是化学式。例如 (H2O2) 和 (H2O2)3 是化学式。
给定一个化学式,输出所有原子的数量。格式为:第一个(按字典序)原子的名子,跟着它的数量(如果数量大于 1),然后是第二个原子的名字(按字典序),跟着它的数量(如果数量大于 1),以此类推。
示例 1:
输入:
formula = “H2O”
输出: “H2O”
解释:
原子的数量是 {‘H’: 2, ‘O’: 1}。
示例 2:
输入:
formula = “Mg(OH)2”
输出: “H2MgO2”
解释:
原子的数量是 {‘H’: 2, ‘Mg’: 1, ‘O’: 2}。
示例 3:
输入:
formula = “K4(ON(SO3)2)2”
输出: “K4N2O14S4”
解释:
原子的数量是 {‘K’: 4, ‘N’: 2, ‘O’: 14, ‘S’: 4}。
注意:
所有原子的第一个字母为大写,剩余字母都是小写。
formula的长度在[1, 1000]之间。
formula只包含字母、数字和圆括号,并且题目中给定的是合法的化学式。
链接:https://leetcode-cn.com/problems/number-of-atoms