返回
秒杀笔试面试:手把手教会你表达式计算问题的万能解法
后端
2023-08-25 20:38:27
双栈算法:征服表达式计算江湖的利器
在程序员的进阶之路上,表达式计算问题宛若一座巍峨高山,横亘在求职面试的关口。双栈算法,犹如一把屠龙之剑,将这道难题斩于马下。
双栈算法:化繁为简的秘诀
双栈算法遵循这样一个核心思想:将表达式的元素(操作数和运算符)依次压入两个栈中,通过依次处理这些元素来计算表达式的值。
算法原理:
- 将表达式的第一个元素压入操作数栈。
- 依次处理表达式的后续元素:
- 如果是操作数,压入操作数栈。
- 如果是运算符,从操作数栈弹出两个操作数,进行计算,将结果压入操作数栈。
- 重复步骤 2,直到表达式的所有元素都被处理完。
- 此 时,操作数栈顶的元素就是表达式的值。
算法步骤:
1. 创建两个栈:操作数栈和运算符栈。
2. 将表达式的第一个元素压入操作数栈。
3. 依次处理表达式的后续元素:
* 如果是操作数,压入操作数栈。
* 如果是运算符,从操作数栈弹出两个操作数,进行计算,将结果压入操作数栈。
4. 重复步骤 3,直到表达式的所有元素都被处理完。
5. 操作数栈顶的元素就是表达式的值。
代码实现:
def evaluate_expression(expression):
"""
Evaluates the given expression using the double stack algorithm.
Args:
expression: The expression to evaluate.
Returns:
The value of the expression.
"""
# Create two stacks: operand stack and operator stack.
operand_stack = []
operator_stack = []
# Tokenize the expression.
tokens = expression.split()
# Process the tokens one by one.
for token in tokens:
# If the token is an operand, push it to the operand stack.
if token.isnumeric():
operand_stack.append(int(token))
# If the token is an operator, pop two operands from the stack, perform the
# operation, and push the result back to the stack.
else:
operand2 = operand_stack.pop()
operand1 = operand_stack.pop()
result = perform_operation(token, operand1, operand2)
operand_stack.append(result)
# The value of the expression is the top element of the operand stack.
return operand_stack[-1]
def perform_operation(operator, operand1, operand2):
"""
Performs the given operation on the two given operands.
Args:
operator: The operator to perform.
operand1: The first operand.
operand2: The second operand.
Returns:
The result of the operation.
"""
if operator == "+":
return operand1 + operand2
elif operator == "-":
return operand1 - operand2
elif operator == "*":
return operand1 * operand2
elif operator == "/":
return operand1 / operand2
else:
raise ValueError("Invalid operator: {}".format(operator))
实战演练:用双栈算法秒杀 LeetCode
题目: 给定一个中缀表达式,计算其值。
示例:
Input: "1 + 2 * 3"
Output: 7
思路:
- 将中缀表达式转换为后缀表达式(逆波兰表达式)。
- 利用双栈算法计算后缀表达式的值。
代码实现:
def evaluate_expression(expression):
"""
Evaluates the given expression using the double stack algorithm.
Args:
expression: The expression to evaluate.
Returns:
The value of the expression.
"""
# Convert the expression to postfix notation.
postfix_expression = infix_to_postfix(expression)
# Evaluate the postfix expression using the double stack algorithm.
return evaluate_postfix_expression(postfix_expression)
def infix_to_postfix(expression):
"""
Converts the given infix expression to postfix notation.
Args:
expression: The infix expression to convert.
Returns:
The postfix notation of the expression.
"""
# Create two stacks: operator stack and output stack.
operator_stack = []
output_stack = []
# Tokenize the expression.
tokens = expression.split()
# Process the tokens one by one.
for token in tokens:
# If the token is an operand, push it to the output stack.
if token.isnumeric():
output_stack.append(token)
# If the token is an operator, pop operators from the operator stack
# until we find an operator with lower precedence. Push the popped
# operators to the output stack. Then, push the current operator to
# the operator stack.
else:
while operator_stack and precedence(token) <= precedence(operator_stack[-1]):
output_stack.append(operator_stack.pop())
operator_stack.append(token)
# Pop all the remaining operators from the operator stack and push them
# to the output stack.
while operator_stack:
output_stack.append(operator_stack.pop())
# The postfix notation of the expression is the sequence of elements in
# the output stack.
return " ".join(output_stack)
def precedence(operator):
"""
Returns the precedence of the given operator.
Args:
operator: The operator whose precedence is to be returned.
Returns:
The precedence of the operator.
"""
if operator in "+-":
return 1
elif operator in "*/":
return 2
else:
raise ValueError("Invalid operator: {}".format(operator))
def evaluate_postfix_expression(expression):
"""
Evaluates the given postfix expression using the double stack algorithm.
Args:
expression: The postfix expression to evaluate.
Returns:
The value of the expression.
"""
# Create two stacks: operand stack and operator stack.
operand_stack = []
operator_stack = []
# Tokenize the expression.
tokens = expression.split()
# Process the tokens one by one.
for token in tokens:
# If the token is an operand, push it to the operand stack.
if token.isnumeric():
operand_stack.append(int(token))
# If the token is an operator, pop two operands from the stack, perform the
# operation, and push the result back to the stack.
else:
operand2 = operand_stack.pop()
operand1 = operand_stack.pop()
result = perform_operation(token, operand1, operand2)
operand_stack.append(result)
# The value of the expression is the top element of the operand stack.
return operand_stack[-1]
def perform_operation(operator, operand1, operand2):
"""
Performs the given operation on the two given operands.
Args:
operator: The operator to perform.
operand1: The first operand.
operand2: The second operand.
Returns:
The result of the operation.
"""
if operator == "+":
return operand1 + operand2
elif operator == "-":
return operand1 - operand2
elif operator == "*":
return operand1 * operand2
elif operator == "/":
return operand1 / operand2
else:
raise ValueError("Invalid operator: {}".format(operator))
结语
双栈算法作为一种通用的表达式计算方法,具有高效、易于实现等优点,是解决表达式计算问题的利器。掌握了双栈算法,你将所向披靡,斩获求职面试中的表达式计算难题,开启程序员进阶的康庄大道。
常见问题解答
-
双栈算法的优点是什么?
双栈算法具有高效、易于实现和通用性强的优点。它适用于各种表达式计算场景,如中缀、后缀和前缀表达式的计算。
-
双栈算法的不足之处是什么?
双栈算法在面对复杂表达式时,可能会遇到运算符优先级和括号匹配等问题。需要额外处理机制来解决这些问题。
-
如何提高双栈算法的效率?
可以采用优化数据结构、减少栈操作次数和预处理表达式等手段来提高双栈算法的效率。
-
双栈算法在实际应用中的场景有哪些?
双栈算法广泛