题目

题目来源:力扣(LeetCode)

给定一个含有数字和运算符的字符串,为表达式添加括号,改变其运算优先级以求出不同的结果。你需要给出所有可能的组合的结果。有效的运算符号包含 +, - 以及 * 。

示例 1:

输入: “2-1-1”
输出: [0, 2]
解释:
((2-1)-1) = 0
(2-(1-1)) = 2

示例 2:

输入: “23-45”
输出: [-34, -14, -10, -10, 10]
解释:
(2(3-(45))) = -34
((23)-(45)) = -14
((2(3-4))5) = -10
(2((3-4)5)) = -10
(((23)-4)5) = 10

思路分析

分治法

采用分治的思想,通过运算符把整个式子分成两部分,去寻找子问题和原问题解的关系。

可以通过运算符把整个式子分成两部分,两部分再利用递归解决。

以 2 3 - 4 5 为例。

2 和 3 - 4 5 两部分,中间是 号相连。

2 3 和 4 5 两部分,中间是 - 号相连。

2 3 - 4 和 5 两部分,中间是 号相连。

有了两部分的结果,然后再通过中间的符号两两计算加入到最终的结果中即可。

比如第一种情况,2 和 3 - 4 5 两部分,中间是 号相连。

2 的解就是 [2],3 - 4 * 5 的解就是 [-5, -17]。

把两部分解通过 * 号计算,最终结果就是 [-10, -34]。

另外两种情况也类似。

然后还需要递归出口。

如果给定的字符串只有数字,没有运算符,那结果就是给定的字符串转为数字。

比如上边的第一种情况,2 的解就是 [2]。

  1. /**
  2. * @param {string} expression
  3. * @return {number[]}
  4. */
  5. var diffWaysToCompute = function (expression) {
  6. var ret = [];
  7. for (var i = 0; i < expression.length; i++) {
  8. // 从字符串中根据索引获取字符
  9. var c = expression.charAt(i);
  10. if (c == '+' || c == '-' || c == '*') {
  11. // 根据操作符,将字符串分为两部分
  12. // 运算符左边的运算结果
  13. var x = diffWaysToCompute(expression.substring(0, i));
  14. // 运算符右边的运算结果
  15. var y = diffWaysToCompute(expression.substring(i + 1));
  16. // 左右两边继续运算
  17. for (var j = 0; j < x.length; j++) {
  18. for (var n = 0; n < y.length; n++) {
  19. switch (c) {
  20. case '+':
  21. ret.push(x[j] + y[n]);
  22. break;
  23. case '-':
  24. ret.push(x[j] - y[n]);
  25. break;
  26. case '*':
  27. ret.push(x[j] * y[n]);
  28. break;
  29. }
  30. }
  31. }
  32. }
  33. }
  34. // ret为空说明当前无运算符,只是单独的数字,直接放入ret中
  35. if (ret.length == 0) {
  36. ret.push(parseInt(expression));
  37. }
  38. return ret;
  39. };