04. Expression Add Operators
β GFG solution to the Expression Add Operators problem: insert +, -, * between digits to reach a target value using DFS & backtracking. π
The problem can be found at the following link: π Question Link
π§© Problem Description
Given a string s
that contains only digits (0-9) and an integer target
, return all possible strings by inserting the binary operators '+'
, '-'
, and/or '*'
between the digits of s
such that the resultant expression evaluates to the target value.
Note:
Operands in the returned expressions should not contain leading zeros. For example,
2 + 03
is not allowed whereas20 + 3
is fine.It is allowed to not insert any of the operators.
Driver code will print the final list of strings in lexicographically smallest order.
π Examples
Example 1
Input: s = "124", target = 9
Output: ["1+2*4"]
Explanation: The valid expression that evaluates to 9 is 1 + 2 * 4
Example 2
Input: s = "125", target = 7
Output: ["1*2+5", "12-5"]
Explanation: The two valid expressions that evaluate to 7 are 1 * 2 + 5 and 12 - 5.
Example 3
Input: s = "12", target = 12
Output: ["12"]
Explanation: s itself matches the target. No other expressions are possible.
Example 4
Input: s = "987612", target = 200
Output: []
Explanation: There are no expressions that can be created from "987612" to evaluate to 200.
π Constraints
$1 \le \text{s.size()} \le 9$
s consists of only digits (0-9)
$-2^{31} \le \text{target} \le 2^{31}-1$
β
My Approach
The optimal approach uses Backtracking with Expression Evaluation to explore all possible ways to insert operators between digits:
Backtracking with DFS
Initialize Variables:
Use recursive DFS to explore all possible placements of operators.
Track three critical values: current position
i
, running evaluationval
, and previous operandprev
.Build expression string
path
as we recurse.
Base Case:
When we reach the end of string (
i == s.length()
), check ifval == target
.If yes, add the current
path
to results.
Recursive Exploration:
Try all possible number formations from current position to end.
For each valid number:
Leading Zero Check: Skip if number starts with '0' and has multiple digits.
First Number: If at position 0, simply take the number as-is.
Subsequent Numbers: Try three operators:
Addition (+): Add current number to evaluation.
Subtraction (-): Subtract current number from evaluation.
Multiplication (*): Handle operator precedence by adjusting with previous operand.
Operator Precedence Handling:
For multiplication, we need to "undo" the last addition/subtraction and apply multiplication first.
Formula:
new_val = val - prev + (prev * cur)
This ensures correct evaluation order without using eval().
Pruning:
Skip numbers with leading zeros (except single '0').
This reduces the search space significantly.
π Time and Auxiliary Space Complexity
Expected Time Complexity: O(4^n), where n is the length of the string. At each position, we have up to 4 choices: no operator, +, -, or *. In practice, it's closer to O(3^n) due to pruning and the constraint that we must place operators between valid numbers.
Expected Auxiliary Space Complexity: O(n), where n is the length of the string. This accounts for the recursion call stack depth and the temporary string being built during backtracking. The output space is not counted toward auxiliary space complexity.
βοΈ Code (C)
char** findExpr(char* s, int target, int* returnSize) {
int cap = 1000, cnt = 0, len = strlen(s);
char** res = malloc(cap * sizeof(char*));
void dfs(int i, long val, long prev, char* path, int plen) {
if (i == len) {
if (val == target) {
res[cnt] = malloc(plen + 1);
strcpy(res[cnt++], path);
if (cnt == cap) res = realloc(res, (cap *= 2) * sizeof(char*));
}
return;
}
for (int j = i; j < len; j++) {
if (j > i && s[i] == '0') break;
long cur = 0;
for (int k = i; k <= j; k++) cur = cur * 10 + (s[k] - '0');
char num[20]; sprintf(num, "%ld", cur);
int nlen = strlen(num);
if (i == 0) {
strcpy(path, num);
dfs(j + 1, cur, cur, path, nlen);
} else {
path[plen] = '+'; strcpy(path + plen + 1, num);
dfs(j + 1, val + cur, cur, path, plen + 1 + nlen);
path[plen] = '-'; strcpy(path + plen + 1, num);
dfs(j + 1, val - cur, -cur, path, plen + 1 + nlen);
path[plen] = '*'; strcpy(path + plen + 1, num);
dfs(j + 1, val - prev + prev * cur, prev * cur, path, plen + 1 + nlen);
}
}
}
char path[100];
dfs(0, 0, 0, path, 0);
*returnSize = cnt;
return res;
}
π§βπ» Code (C++)
class Solution {
public:
vector<string> findExpr(string& s, int target) {
vector<string> res;
function<void(int, long, long, string)> dfs = [&](int i, long val, long prev, string path) {
if (i == s.size()) {
if (val == target) res.push_back(path);
return;
}
for (int j = i; j < s.size(); j++) {
if (j > i && s[i] == '0') break;
long cur = stol(s.substr(i, j - i + 1));
if (i == 0) dfs(j + 1, cur, cur, to_string(cur));
else {
dfs(j + 1, val + cur, cur, path + "+" + to_string(cur));
dfs(j + 1, val - cur, -cur, path + "-" + to_string(cur));
dfs(j + 1, val - prev + prev * cur, prev * cur, path + "*" + to_string(cur));
}
}
};
dfs(0, 0, 0, "");
return res;
}
};
β Code (Java)
class Solution {
public ArrayList<String> findExpr(String s, int target) {
ArrayList<String> res = new ArrayList<>();
dfs(s, target, 0, 0, 0, "", res);
return res;
}
void dfs(String s, int target, int i, long val, long prev, String path, ArrayList<String> res) {
if (i == s.length()) {
if (val == target) res.add(path);
return;
}
for (int j = i; j < s.length(); j++) {
if (j > i && s.charAt(i) == '0') break;
long cur = Long.parseLong(s.substring(i, j + 1));
if (i == 0) dfs(s, target, j + 1, cur, cur, "" + cur, res);
else {
dfs(s, target, j + 1, val + cur, cur, path + "+" + cur, res);
dfs(s, target, j + 1, val - cur, -cur, path + "-" + cur, res);
dfs(s, target, j + 1, val - prev + prev * cur, prev * cur, path + "*" + cur, res);
}
}
}
}
π Code (Python)
class Solution:
def findExpr(self, s, target):
res = []
def dfs(i, val, prev, path):
if i == len(s):
if val == target: res.append(path)
return
for j in range(i, len(s)):
if j > i and s[i] == '0': break
cur = int(s[i:j+1])
if i == 0: dfs(j + 1, cur, cur, str(cur))
else:
dfs(j + 1, val + cur, cur, path + '+' + str(cur))
dfs(j + 1, val - cur, -cur, path + '-' + str(cur))
dfs(j + 1, val - prev + prev * cur, prev * cur, path + '*' + str(cur))
dfs(0, 0, 0, '')
return res
π§ Contribution and Support
For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: π¬ Any Questions?. Let's make this learning journey more collaborative!
β If you find this helpful, please give this repository a star! β
πVisitor Count
Last updated