题目
给你一个由数字和运算符组成的字符串 expression ,按不同优先级组合数字和运算符,计算并返回所有可能组合的结果。你可以 按任意顺序 返回答案。
生成的测试用例满足其对应输出值符合 32 位整数范围,不同结果的数量不超过 104 。
示例 1:
输入: expression = "2-1-1"
输出: [0,2]
解释:
((2-1)-1) = 0
(2-(1-1)) = 2
示例 2:
输入: expression = "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
提示:
1 <= expression.length <= 20expression由数字和算符'+'、'-'和'*'组成。- 输入表达式中的所有整数值在范围
[0, 99]
思路
解法一: 分治
解法思路🔗: 241. 为运算表达式设计优先级 - Python/Golang 分治算法
将式子从任一个符号分开,左边的组合 运算 右边的组合,就是这个符号所在的所有的解,然后遍历中间所有的符号,就是这道题的所有解。左 运算 右的组合,和归并排序有点类似,
分治三步走
- 1、分解:按运算符分成左右两部分,分别求解
- 2、解决:实现一个递归函数,输入算式,返回算式解式
- 3、合并:根据运算符合并左右两部分的解,得到最终解
代码一: 分治
class Solution:
def diffWaysToCompute(self, expression: str) -> List[int]:
# 分治思想
res = []
for i, char in enumerate(expression):
# 当char为("+", "-", "*")时,开始
if char in ("+", "-", "*"):
# 根据char的位置,区分为[...,i),(i+1,...]区间进行分解
left = self.diffWaysToCompute(expression[:i])
right = self.diffWaysToCompute(expression[i+1:])
# 根据char字符进行结果的查找
for l in left:
for r in right:
if char == "+":
res.append(l+r)
elif char == "-":
res.append(l-r)
else:
res.append(l*r)
if len(res) == 0:
x = 0
for i in range(len(expression)):
x = x * 10 + int(expression[i])
res.append(x)
return res
解法二: dfs深度优先
解法思路🔗: 241. 为运算表达式设计优先级 - 【宫水三叶】运用 DFS 爆搜所有方案
根据运算符将式子分为左右2部分,设计递归函数 dfs(l,r),根据i位置的符号区分为 [l,i-1]和[i+1,r],最终答案为 dfs(0,n-1),为搜索子串expression(l,r)的所有运算结果。
dfs的出口就是,当l,r的区间只剩所有数字,不包含运算符,计算出数字。
对任意区间 expression(l,r):通过枚举(l,r)范围内的所有运算符来进行搜索,对于任意expression[i]为运算符,第一层遍历左边的所有结果l1,第二层遍历右边所有结果l2,对l1和l2进行expression[i]运算,得到expression[i]在(l,r)上的所有值,最后遍历所有长度的所有expression[i]就得到最终结果。
代码二: dfs深度遍历
使用for循环判断头尾,注意python中range是左闭右开区间,所以在遍历时需要赋值r+1。
class Solution:
def diffWaysToCompute(self, expression: str) -> List[int]:
def dfs(l, r):
res = []
for i in range(l, r+1):
if expression[i] >= '0' and expression[i] <= '9':
continue
left = dfs(l, i-1)
right = dfs(i+1, r)
for l1 in left:
for r1 in right:
cur = 0
if expression[i] == "+":
cur = l1 + r1
elif expression[i] == "-":
cur = l1 - r1
else:
cur = l1 * r1
res.append(cur)
if len(res) == 0:
cur = 0
for i in range(l, r+1):
cur = cur * 10 + int(expression[i])
res.append(cur)
return res
return dfs(0, len(expression)-1)
代码三: dfs遍历代码二
只是将for循环用while循环代替,更容易理解。
class Solution:
def diffWaysToCompute(self, expression: str) -> List[int]:
def dfs(l, r):
res = []
i = l
while i <= r:
if expression[i] >= '0' and expression[i] <= '9':
i += 1
continue
left = dfs(l, i-1)
right = dfs(i+1, r)
for l1 in left:
for r1 in right:
cur = 0
if expression[i] == "+":
cur = l1 + r1
elif expression[i] == "-":
cur = l1 - r1
else:
cur = l1 * r1
res.append(cur)
i += 1
if len(res) == 0:
j = l
cur = 0
while j <= r:
cur = cur * 10 + int(expression[j])
j += 1
res.append(cur)
return res
return dfs(0, len(expression) - 1)