Basic Calculator - LeetCode 224

本文介绍如何通过栈实现一个基本的计算器,用于评估包含加减运算和括号的简单表达式字符串。代码示例展示了从输入表达式到计算结果的完整流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:
Implement a basic calculator to evaluate a simple expression string.
The expression string may contain open ( and closing parentheses ), the plus + or minus sign -, non-negative integers and 
empty spaces .
You may assume that the given expression is always valid.
Some examples:
"1 + 1" = 2
" 2-1 + 2 " = 3
"(1+(4+5+2)-3)+(6+8)" = 23
Note: Do not use the eval built-in library function.
Hide Tags Stack Math
分析:
该题要实现一个带有括号优先级的加减法计算器,实质就是栈的使用。不多说了,直接看代码注释吧

/**///56ms//*/
class Solution {
public:
    int docompute(int a,int b,char opd){ //计算a opera b
	if(opd == '+')
	    return a + b;
	if(opd == '-')
	    return a - b;		
	}
    bool isopd(char ch){ //判断是否是运算符
	return (ch == '+' || ch == '-' || ch == '(' || ch == ')'||ch == '=');
    }
    int calculate(string s) {
	int len = s.size();
	if(len == 0)
	    return 0;
	s.push_back('='); //在表达式末尾加上'=',方便判断是否计算结束		
        stack<char> opd;
	opd.push('='); //在运算符栈底添加'=',方便判断是否计算结束

	stack<int> num; //操作数栈
	int i = 0;
	while( i <= len){ 
	    if(isdigit(s[i])){ // 如果是数字字符,则转换为整数后压入操作数栈。注意处理多位数的情况
		int dat = 0;
	        while(isdigit(s[i])){
		    dat = dat * 10 + (s[i]-'0');
			i++;
		}				
		num.push(dat);				
	    }
	    else if(isopd(s[i])){ //如果是运算符 
		if(s[i] == '('){  '('直接压入栈
		    opd.push(s[i]);
		    i++;
		    continue;
		}
		if(s[i] == ')'){  
                //遇到')'时,需判断栈顶运算符是'+'或'-',直接取出计算后将结果要入操作数栈;
                //否则只能是'(',弹出栈.
                //继续处理下一个字符
		    char oper = opd.top(); 
		    opd.pop();
		    if(oper == '+' || oper == '-'){
	                int a = 0, b = 0;
			b = num.top();
			num.pop();
			a = num.top();
			num.pop();
			int re = docompute(a,b,oper);
			num.push(re);					
			opd.pop(); //pop teh '('
		    }
		    i++; 
		    continue;
		}	
	        if(s[i] == '+' || s[i] == '-'){  //遇到'+'或‘-’,看运算符栈顶
		    char oper = opd.top(); 
		    if(oper == '=' || oper == '('){ //若运算符栈顶是'='或'(',直接将当前运算符压入栈
			opd.push(s[i]);
			i++;
			continue;
		    }
		    else{  //栈顶为'+'或'-',取出计算
			opd.pop();
			int a = 0, b = 0;
			b = num.top();
			num.pop();
			a = num.top();
			num.pop();
			int re = docompute(a,b,oper);
			num.push(re);
			continue;
		    }
		}
		if(s[i]=='='){ //遇到'=',
		    if(opd.top() == '=') //栈顶也是'=',表示计算结束,返回结果
			return num.top();
		    else{ //不是等于,表明还有运算符,且只能是'+'或'-',取出计算结果
			char oper = opd.top();
			opd.pop();
			int a = 0, b = 0;
			b = num.top();
		        num.pop();
			a = num.top();
			num.pop();
			int re = docompute(a,b,oper);
			//cout << re << endl;
			num.push(re);
			continue;
		    }
		}

            } 
	    else //跳过空格
		i++;
        }
		
    }
};


### LeetCode 224 Basic Calculator 解答与解析 #### 表达式求值的核心挑战 表达式求值的关键在于处理括号和运算符优先级。对于给定的有效简单表达式字符串,目标是在不使用内置 `eval` 函数的情况下计算其结果[^1]。 #### 使用栈实现解决方案 为了应对这一挑战,可以采用栈来辅助完成操作数和运算符的管理: - **初始化变量** - 创建两个栈分别用于存储数字 (`numStack`) 和操作符 (`opStack`) - 设置当前数值缓存器 `currentNum` - **遍历输入串中的字符** - 如果遇到的是数字,则更新 `currentNum` - 若碰到加减号或右括号时,需将之前累积起来的操作数压入到 `numStack` 中,并重置 `currentNum` - 当遇见左括号时直接跳过即可;而当碰见右括号则意味着要开始结算内部子表达式的值直到最近的一个未匹配的左括号位置为止 - **处理最终剩余项** - 循环结束后可能还会有残留的数据存在于栈内或是暂存在 `currentNum` 变量里,因此最后一步是要把它们也加入到总的结果当中去 下面是具体的 Python 实现方式: ```python def calculate(s: str) -> int: num_stack = [] op_stack = [] current_num = 0 sign = '+' for i, char in enumerate(s): if char.isdigit(): current_num = current_num * 10 + int(char) if (not char.isdigit() and not char.isspace()) or i == len(s)-1: if sign == '-': num_stack.append(-current_num) elif sign == '+': num_stack.append(current_num) if char != ')': sign = char else: temp_sum = 0 while isinstance(op_stack[-1], int): temp_sum += op_stack.pop() op_stack.pop() # pop out '(' num_stack.append(temp_sum) current_num = 0 if char == '(': op_stack.append(sign) op_stack.append('(') sign = '+' return sum(num_stack) + sum([item for item in op_stack if isinstance(item, int)]) ``` 此方法通过巧妙利用栈结构解决了带有嵌套括号情况下的算术表达式求解问题,在时间复杂度上达到了 O(n),其中 n 是字符串长度[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值