加载中...
282-给表达式添加运算符(Expression Add Operators)
发表于:2021-12-03 | 分类: 困难
字数统计: 1.7k | 阅读时长: 7分钟 | 阅读量:

原文链接: https://leetcode-cn.com/problems/expression-add-operators

英文原文

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: ["1*2*3","1+2+3"]
Explanation: Both "1*2*3" and "1+2+3" evaluate to 6.

Example 2:

Input: num = "232", target = 8
Output: ["2*3+2","2+3*2"]
Explanation: Both "2*3+2" and "2+3*2" evaluate to 8.

Example 3:

Input: num = "105", target = 5
Output: ["1*0+5","10-5"]
Explanation: Both "1*0+5" and "10-5" evaluate to 5.
Note that "1-05" is not a valid expression because the 5 has a leading zero.

Example 4:

Input: num = "00", target = 0
Output: ["0*0","0+0","0-0"]
Explanation: "0*0", "0+0", and "0-0" all evaluate to 0.
Note that "00" is not a valid expression because the 0 has a leading zero.

Example 5:

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.
  • -231 <= target <= 231 - 1

中文题目

给定一个仅包含数字 0-9 的字符串 num 和一个目标值整数 target ,在 num 的数字之间添加 二元 运算符(不是一元)+- 或 * ,返回所有能够得到目标值的表达式。

 

示例 1:

输入: num = "123", target = 6
输出: ["1+2+3", "1*2*3"] 

示例 2:

输入: num = "232", target = 8
输出: ["2*3+2", "2+3*2"]

示例 3:

输入: num = "105", target = 5
输出: ["1*0+5","10-5"]

示例 4:

输入: num = "00", target = 0
输出: ["0+0", "0-0", "0*0"]

示例 5:

输入: num = "3456237490", target = 9191
输出: []

 

提示:

  • 1 <= num.length <= 10
  • num 仅含数字
  • -231 <= target <= 231 - 1

通过代码

高赞题解

回溯算法

最开始的想法是先使用 DFS 搜出来所有的表达式,然后套用 (题解)227. 基本计算器 II 方案,计算所有表达式的结果,并将计算结果为 $target$ 的表达式加到结果集。

假设原字符串 $num$ 的长度为 $n$,由于每个位置之间存在四种插入决策(不插入符号、+-*),共有 $n - 1$ 个位置需要决策,因此搜索所有表达式的复杂度为 $O(4^{n - 1})$;同时需要对所有的表达式执行计算,复杂度为 $O(n)$,整体复杂度为 $O(n * 4^{n - 1})$。

添加运算符后的表达式长度不会超过 $20$,因此总的计算量应该是在 $10^7$ 以内,但可能是因为常数问题超时了(各种优化双栈操作也还是 TLE,在这上面浪费了好多时间 QWQ)。

因此,我们需要考虑在搜索过程中进行计算,以避免使用 (题解)227. 基本计算器 II 这种常数较大的计算方式。

我们考虑如果只有 +- 的话,可以很容易将运算和回溯搜索所有表达进行结合。但当存在 * 时,由于存在运算优先级的问题,我们需要记录形如 a + b * c 中的乘法部分。

实现上,除了记录当前决策到原串 $num$ 的哪一位 $u$,以及当前的运算结果 $cur$ 以外,还需要额外记录最后一次的计算结果 $prev$,然后在决策表达式中的第 $k$ 个部分时,对本次添加的运算符合做分情况讨论:

  • 如果本次添加的 + 操作,且第 $k$ 项的值是 $next$:那么直接使用 $cur + next$ 来更新 $cur$,同时 $next$ 作为下一次的 $prev$;
  • 如果本次添加的 - 操作,且第 $k$ 项的值是 $next$:同理,那么直接使用 $cur - next$ 来更新 $cur$,同时 $-next$ 作为下一次的 $prev$;
  • 如果本次添加的 * 操作,且第 $k$ 项的值是 $next$:此时需要考虑运算符的优先级问题,由于本次的 $next$ 是与上一次的操作数 $prev$ 执行乘法,而 $cur$ 已经累加了 $prev$ 的影响,因此需要先减去 $prev$,再加上 $prev * next$,以此来更新 $cur$,同时 $prev * next$ 也作为下一次的 $prev$。

一些细节:需要注意前导零($0$ 单独作为一位是被允许的,但是多位且首部为 $0$ 是不允许的)以及 +- 不作为一元运算符(运算符不能出现在表达式的首部)的情况。

代码:

[]
class Solution { List<String> ans = new ArrayList<>(); String s; int n, t; public List<String> addOperators(String num, int target) { s = num; n = s.length(); t = target; dfs(0, 0, 0, ""); return ans; } void dfs(int u, long prev, long cur, String ss) { if (u == n) { if (cur == t) ans.add(ss); return ; } for (int i = u; i < n; i++) { if (i != u && s.charAt(u) == '0') break; long next = Long.parseLong(s.substring(u, i + 1)); if (u == 0) { dfs(i + 1, next, next, "" + next); } else { dfs(i + 1, next, cur + next, ss + "+" + next); dfs(i + 1, -next, cur - next, ss + "-" + next); long x = prev * next; dfs(i + 1, x, cur - prev + x, ss + "*" + next); } } } }
  • 时间复杂度:$O(4^{n})$
  • 空间复杂度:$O(4^{n})$

总结

该做法表面上,只是实现了边搜索边计算的功能,但其本质上是利用了实数集 $S$ 和运算符 +- 的本质也是 +)和 * 能够组成代数系统。

利用代数系统 $(S, +, *)$,我们可以确保运算过程中的任意一个中间结果,都能使用形如 a + b * c 的形式进行表示,因此我们只需要多维护一个后缀串结果即可。

而代数系统的相关知识,以及如何确定能否作为一个代数系统,有兴趣的同学可以尝试去了解一下。


最后

如果有帮助到你,请给题解点个赞和收藏,让更多的人看到 ~ (“▔□▔)/

也欢迎你 关注我(公主号后台回复「送书」即可参与长期看题解学算法送实体书活动)或 加入「组队打卡」小群 ,提供写「证明」&「思路」的高质量题解。

所有题解已经加入 刷题指南,欢迎 star 哦 ~

统计信息

通过次数 提交次数 AC比率
20135 41517 48.5%

提交历史

提交时间 提交结果 执行时间 内存消耗 语言

相似题目

题目 难度
逆波兰表达式求值 中等
基本计算器 困难
基本计算器 II 中等
为运算表达式设计优先级 中等
目标和 中等
上一篇:
279-完全平方数(Perfect Squares)
下一篇:
283-移动零(Move Zeroes)
本文目录
本文目录