给表达式添加运算符
282.给表达式添加运算符
题目描述
思路:回溯
回溯
假定字符串num长度为n,为构建表达式,可以往num中间的n-1个空隙添加+号、-号、*号或者不添加符号。
使用回溯法模拟整个过程,从左往右构建表达式,并实时计算表达式的结果。由于乘法运算符优先级高于加减法运算符,还需要保存最后一个连乘串的运算结果。
定义递归回溯函数backtrack(cur, i, res, mul),其中:
- cur表示当前构建出的表达式;
- i表示枚举到num中的第i个数字;
- res表示当前表达式计算的结果;
- mul表示表达式最后一个连乘串的结果。
该函数需要讨论两种情况: - i = n,说明表达式构造完成,如果此时res与target相等,则找到了一个可行解,将cur作为答案返回放入答案列表中,结束当前递归;
- i < n,枚举当前表达式末尾要添加的符号(+、-、*)以及该符号之后需要截取多少位数字。设该符号之后的数字为val,按符号分类讨论:
- 若添加+号,则res增加val,且val单独组成表达式最后一个连乘串;
- 若添加-号,则res减少val,且-val单独组成表达式最后一个连乘串;
- 若添加号,由于乘法运算优先级高于加法和减法运算,我们需要对res撤销之前mul的计算结果,并添加新的连乘结果mulval,也就是将res减少mul并增加mul*val。
class Solution:
def addOperators(self, num: str, target: int) -> List[str]:
n = len(num)
ans = []
def backtrack(cur, i, res, mul):
if i == n:
if res == target:
ans.append("".join(cur))
return
signIndex = len(cur)
if i > 0:
# 占位,下面填充符号
cur.append("")
val = 0
# 枚举截取的数字长度
for j in range(i, n):
# 数字可以是单个0,但不能是前导0
if j > i and num[i] == '0':
break
val = val * 10 + int(num[j])
cur.append(num[j])
# 表达式开头不加符号
if i == 0:
backtrack(cur, j+1, val, val)
# 枚举符号
else:
cur[signIndex] = '+'; backtrack(cur, j+1, res+val, val)
cur[signIndex] = '-'; backtrack(cur, j+1, res-val, -val)
cur[signIndex] = '*'; backtrack(cur, j+1, res-mul+mul*val, mul*val)
del cur[signIndex:]
backtrack([], 0, 0, 0)
return ans