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.
For example:
num
= "123", target
= 6. Output: ["1*2*3","1+2+3"]
num
= "232", target
= 8. Output: ["2*3+2","2+3*2"]
num
= "3456237490", target
= 9191. Output: []
Explain your approach, especially how to handle the operator precedence and avoid leading zeros. Discuss the time and space complexity of your solution.
We can use a brute-force approach to generate all possible expressions by inserting '+', '-', or '*' between the digits of the input string num
. We'll evaluate each expression and check if it equals the target value.
This approach will generate all possible combinations, but is very inefficient due to the exponential nature of possible expressions.
We can optimize the solution using backtracking. The idea is to explore possible expressions by recursively building them, but with a more efficient evaluation method. We'll keep track of the current expression, the current result, and the last operand used for multiplication.
Base Case: If we have processed all digits and the current result equals the target, add the expression to the result list.
Recursive Step: For each possible split point in the remaining digits:
Backtracking: After each recursive call, undo the changes to explore other possibilities.
This approach is more efficient than the naive solution because it avoids generating and evaluating unnecessary expressions. The key optimization is the use of the prevOperand
variable to correctly handle multiplication. Without this the algorithm will fail on test cases such as 1+2*3
because it will evaluate the 1+2
before multiplying by 3
.
long
to prevent integer overflow.import java.util.ArrayList;
import java.util.List;
class Solution {
public List<String> addOperators(String num, int target) {
List<String> result = new ArrayList<>();
if (num == null || num.length() == 0) {
return result;
}
helper(result, "", num, target, 0, 0, 0);
return result;
}
private void helper(List<String> result, String expression, String num, int target,
int pos, long currentResult, long prevOperand) {
if (pos == num.length()) {
if (currentResult == target) {
result.add(expression);
}
return;
}
for (int i = pos; i < num.length(); i++) {
if (i != pos && num.charAt(pos) == '0') {
break; // Avoid leading zeros
}
long currentOperand = Long.parseLong(num.substring(pos, i + 1));
if (pos == 0) {
helper(result, String.valueOf(currentOperand), num, target, i + 1,
currentOperand, currentOperand);
} else {
helper(result, expression + "+" + currentOperand, num, target, i + 1,
currentResult + currentOperand, currentOperand);
helper(result, expression + "-" + currentOperand, num, target, i + 1,
currentResult - currentOperand, currentOperand);
helper(result, expression + "*" + currentOperand, num, target, i + 1,
currentResult - prevOperand + prevOperand * currentOperand, currentOperand * prevOperand);
}
}
}
}