题目

Given a string of numbers and operators, return all possible results from computing all the different possible ways to group numbers and operators. The valid operators are +, - and *.

Example 1:

  1. Input: "2-1-1"
  2. Output: [0, 2]
  3. Explanation:
  4. ((2-1)-1) = 0
  5. (2-(1-1)) = 2

Example 2:

  1. Input: "2*3-4*5"
  2. Output: [-34, -14, -10, -10, 10]
  3. Explanation:
  4. (2*(3-(4*5))) = -34
  5. ((2*3)-(4*5)) = -14
  6. ((2*(3-4))*5) = -10
  7. (2*((3-4)*5)) = -10
  8. (((2*3)-4)*5) = 10

题意

给定一串数字表达式,可以任意添加括号,求所有可能得到的结果。

思路

难点在于如何添加括号来得到不同的表达式。可以这样考虑,每一个算术表达式都可以拆分成三个部分,左操作数、操作符、右操作数,即 0241. Different Ways to Add Parentheses (M) - 图1 的形式,只要改变每个括号内操作数的个数,得到的一定是不一样的括号形式;而每一个括号里又是一个算数表达式,可以递归的进行处理,最终就能得到所有括号的组合形式。


代码实现

Java

分治法

  1. class Solution {
  2. public List<Integer> diffWaysToCompute(String input) {
  3. if (input.isEmpty()) {
  4. return new ArrayList<>();
  5. }
  6. // 先将字符串拆分成操作数集合和操作符集合,便于处理
  7. List<Character> ops = new ArrayList<>();
  8. List<Integer> nums = new ArrayList<>();
  9. int num = 0;
  10. for (char c : input.toCharArray()) {
  11. if (Character.isDigit(c)) {
  12. num = num * 10 + c - '0';
  13. } else {
  14. ops.add(c);
  15. nums.add(num);
  16. num = 0;
  17. }
  18. }
  19. nums.add(num);
  20. return diff(nums, ops, 0, nums.size() - 1);
  21. }
  22. private List<Integer> diff(List<Integer> nums, List<Character> ops, int left, int right) {
  23. List<Integer> list = new ArrayList<>();
  24. if (left == right) {
  25. list.add(nums.get(left));
  26. return list;
  27. }
  28. for (int mid = left; mid < right; mid++) {
  29. List<Integer> part1 = diff(nums, ops, left, mid);
  30. List<Integer> part2 = diff(nums, ops, mid + 1, right);
  31. for (int i = 0; i < part1.size(); i++) {
  32. for (int j = 0; j < part2.size(); j++) {
  33. int num1 = part1.get(i), num2 = part2.get(j);
  34. char op = ops.get(mid);
  35. list.add(op == '-' ? num1 - num2 : op == '+' ? num1 + num2 : num1 * num2);
  36. }
  37. }
  38. }
  39. return list;
  40. }
  41. }

记忆化优化

  1. class Solution {
  2. public List<Integer> diffWaysToCompute(String input) {
  3. return diffWaysToCompute(input, new HashMap<>());
  4. }
  5. private List<Integer> diffWaysToCompute(String input, Map<String, List<Integer>> record) {
  6. List<Integer> list = new ArrayList<>();
  7. if (input.isEmpty())
  8. return list;
  9. if (record.containsKey(input))
  10. return record.get(input);
  11. for (int i = 0; i < input.length(); i++) {
  12. // 根据操作符划分左右
  13. if (!Character.isDigit(input.charAt(i))) {
  14. char op = input.charAt(i);
  15. List<Integer> left = diffWaysToCompute(input.substring(0, i), record);
  16. List<Integer> right = diffWaysToCompute(input.substring(i + 1), record);
  17. for (int p = 0; p < left.size(); p++) {
  18. for (int q = 0; q < right.size(); q++) {
  19. int num1 = left.get(p), num2 = right.get(q);
  20. list.add(op == '-' ? num1 - num2 : op == '+' ? num1 + num2 : num1 * num2);
  21. }
  22. }
  23. }
  24. }
  25. // list为空,说明不存在操作符,input为完整数字
  26. if (list.size() == 0) {
  27. list.add(Integer.parseInt(input));
  28. }
  29. record.put(input, list);
  30. return list;
  31. }
  32. }