Given a string
num
that contains only digits and an integer target
, return all possibilities to insert the binary operators '+'
, '-'
, and/or '*'
between the digits of num
so that the resultant expression evaluates to the target
value.Note that operands in the returned expressions should not contain leading zeros.
Example 1:
Input: num = “123”, target = 6
Output: [“123”,”1+2+3”]
Explanation: Both “123” and “1+2+3” evaluate to 6.
Example 2:
Input: num = “232”, target = 8
Output: [“23+2”,”2+32”]
Explanation: Both “23+2” and “2+32” evaluate to 8.
Example 3:
Input: num = “3456237490”, target = 9191
Output: []
Explanation: There are no expressions that can be created from “3456237490” to evaluate to 9191.
Constraints:
1 <= num.length <= 10
num
consists of only digits.*
-2<sup>31</sup> <= target <= 2<sup>31</sup> - 1
题目大意:
求一串数字加入加减乘能得到target的所有可能性
解题思路:
求所有可能用DFS。属于分割型DFS,在数位之间加符号,数位可以是1个到多个。
一轮递归分割出符号 + 数字
另一种选择是数字 + 符号,但需要额外变量sign,因为不能立刻计算到结果。也不符合正常逻辑。所以选择前者。
由于运算都是二元,也就是用上述分割法,第一个数要特别处理。所以DFS中要特别处理第一个数。这样可以开始写加减。引入prev_res作为DFS参数,这样只要prev_res 加减 该轮数字即可得到该轮结果。用DFS模板5个标准参数外加prev_res:1
def dfs(self, num, st, target, prev_res, path, res):
这样只处理加减的DFS比较容易实现
最大难点在于乘法,参考LeetCode 227 Basic Calculator II,加减和乘除属于两层计算需要分别处理,所以引入新参数prev_multi_res,用于保存乘法结果,而刚才的命名为prev_add_res保存加减乘的全部结果1
def dfs(self, num, st, target, prev_add_res, prev_multi_res, path, res):
举例2+3*4,按照原来的逻辑会计算到2+3=5,但此时如果遇到乘号,就要重新计算加法结果,先减去乘法结果,退回到2,再计算3*4=12这是乘法结果,再加回2得到新加法结果。进一步理解prev_multi_res,如果该轮是加减法,仍要将该轮的数作为prev_multi_res传到下轮DFS,因为如果下一轮是乘法,它就是第一个乘法的数。
解题步骤:
- 先实现加减法
- 再实现乘法
注意事项:
- 分割型DFS,选择每轮递归分割符号 + 数字。由于运算都是二元,特别处理第一个数
- 引入参数prev_add_res, prev_multi_res. prev_multi_res若是加减,用(+/-)cur_num, 否则用乘法结果prev_multi_res * cur_num。注意若是减法cur_num用负号
- 分割时数字不能有前缀0
- prev_res不用恢复状态因为是标量
Python代码:
1 | def addOperators(self, num: str, target: int) -> List[str]: |
算法分析:
时间复杂度为O(4n)
,空间复杂度O(n)
, 因为每个字符之间都有不加操作符,加3个操作符,所以是4,有n-1个间隔