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:
Input: "2*3-4*5"
(2*(3-(4*5))) = -34
((2*3)-(4*5)) = -14
((2*(3-4))*5) = -10
(2*((3-4)*5)) = -10
(((2*3)-4)*5) = 10
Output: [-34, -14, -10, -10, 10]
解法类似 95题:http://www.jianshu.com/p/948c40b3444d
Solution1:Divide and Conquer
从每个operator将input_str分成左右两部分part1, part2 (Divide),recursiely计算part1和part2的组合结果,再将这两个组合结果Conquer构成从当前operator分的结果。对于每个operator都这样遍历一遍。
Time Complexity: ? Space Complexity: ?
Solution2:Divide and Conquer + Hashmap
Solution1中含有重复计算,2在Solution1的基础上 将已求过的String的结果List<Integer> Mapping保存下来,缓存避免重复计算。
Time Complexity: ? Space Complexity: ?
Solution3:DP写法
dp[i][j] stores all possible results from the i-th integer to the j-th integer (inclusive) in the list
/ length:d \
[i-> j-> ]
操作数数组: [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a..]
更新方式:遍历从d=0..N(不同长度的子串),对于每个d,two loop遍历d范围中的i, j,求出dp[i][i+d]: dp[i][i+d].add(leftNum+rightNum); leftNum is from dp[i][j] list, and rightNum is from dp[j+1][i+d] list.
reference: https://discuss.leetcode.com/topic/26076/java-recursive-9ms-and-dp-4ms-solution
Time Complexity: ? Space Complexity: ?
Solution1 Code:
class Solution {
public List<Integer> diffWaysToCompute(String input) {
List<Integer> result = new LinkedList<Integer>();
for(int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if(c == '+' || c == '-' || c == '*') {
String part1 = input.substring(0, i);
String part2 = input.substring(i + 1);
List<Integer> part1_ret = diffWaysToCompute(part1);
List<Integer> part2_ret = diffWaysToCompute(part2);
for(Integer p1: part1_ret) {
for(Integer p2: part2_ret) {
int r = 0;
switch(c) {
case '+':
r = p1 + p2;
break;
case '-':
r = p1 - p2;
break;
case '*':
r = p1 * p2;
break;
}
result.add(r);
}
}
}
}
// if there is only one operand, no operator
if(result.size() == 0) {
result.add(Integer.valueOf(input));
}
return result;
}
}
Solution2 Code:
public class Solution {
Map<String, List<Integer>> map;
public List<Integer> diffWaysToCompute(String input) {
map = new HashMap<>();
List<Integer> result = new ArrayList<>();
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if (c == '+' || c == '-' || c == '*') {
String part1 = input.substring(0, i);
String part2 = input.substring(i + 1);
List<Integer> part1_ret = map.getOrDefault(part1, diffWaysToCompute(p1));
List<Integer> part2_ret = map.getOrDefault(part2, diffWaysToCompute(p2));
for (Integer p1 : part1_ret) {
for (Integer p2 : part2_ret) {
int r = 0;
switch (c) {
case '+':
r = p1 + p2;
break;
case '-':
r = p1 - p2;
break;
case '*':
r = p1 * i2;
break;
}
res.add(r);
}
}
}
}
if (res.size() == 0) {
res.add(Integer.valueOf(input));
}
map.put(input, result);
return result;
}
}
Solution3 Code:
public List<Integer> diffWaysToCompute(String input) {
List<Integer> result=new ArrayList<>();
if(input==null||input.length()==0) return result;
List<String> ops=new ArrayList<>();
for(int i=0; i<input.length(); i++){
int j=i;
while(j<input.length()&&Character.isDigit(input.charAt(j)))
j++;
ops.add(input.substring(i, j));
if(j!=input.length()) ops.add(input.substring(j, j+1));
i=j;
}
int N=(ops.size()+1)/2; //num of integers
ArrayList<Integer>[][] dp=(ArrayList<Integer>[][]) new ArrayList[N][N];
for(int d=0; d<N; d++){
if(d==0){
for(int i=0; i<N; i++){
dp[i][i]=new ArrayList<>();
dp[i][i].add(Integer.valueOf(ops.get(i*2)));
}
continue;
}
for(int i=0; i<N-d; i++){
dp[i][i+d]=new ArrayList<>();
for(int j=i; j<i+d; j++){
ArrayList<Integer> left=dp[i][j], right=dp[j+1][i+d];
String operator=ops.get(j*2+1);
for(int leftNum:left)
for(int rightNum:right){
if(operator.equals("+"))
dp[i][i+d].add(leftNum+rightNum);
else if(operator.equals("-"))
dp[i][i+d].add(leftNum-rightNum);
else
dp[i][i+d].add(leftNum*rightNum);
}
}
}
}
return dp[0][N-1];
}