Overflow in intermediate arithmetic
Wrong move: Temporary multiplications exceed integer bounds.
Usually fails on: Large inputs wrap around unexpectedly.
Fix: Use wider types, modular arithmetic, or rearranged operations.
Break down a hard problem into reliable checkpoints, edge-case handling, and complexity trade-offs.
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.
Note that a number can contain multiple digits.
Example 1:
Input: num = "123", target = 6 Output: ["1*2*3","1+2+3"] Explanation: Both "1*2*3" and "1+2+3" evaluate to 6.
Example 2:
Input: num = "232", target = 8 Output: ["2*3+2","2+3*2"] Explanation: Both "2*3+2" and "2+3*2" evaluate to 8.
Example 3:
Input: num = "3456237490", target = 9191 Output: [] Explanation: There are no expressions that can be created from "3456237490" to evaluate to 9191.
Constraints:
1 <= num.length <= 10num consists of only digits.-231 <= target <= 231 - 1Problem summary: 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. Note that a number can contain multiple digits.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Math · Backtracking
"123" 6
"232" 8
"3456237490" 9191
evaluate-reverse-polish-notation)basic-calculator)basic-calculator-ii)different-ways-to-add-parentheses)target-sum)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #282: Expression Add Operators
class Solution {
private List<String> ans;
private String num;
private int target;
public List<String> addOperators(String num, int target) {
ans = new ArrayList<>();
this.num = num;
this.target = target;
dfs(0, 0, 0, "");
return ans;
}
private void dfs(int u, long prev, long curr, String path) {
if (u == num.length()) {
if (curr == target) ans.add(path);
return;
}
for (int i = u; i < num.length(); i++) {
if (i != u && num.charAt(u) == '0') {
break;
}
long next = Long.parseLong(num.substring(u, i + 1));
if (u == 0) {
dfs(i + 1, next, next, path + next);
} else {
dfs(i + 1, next, curr + next, path + "+" + next);
dfs(i + 1, -next, curr - next, path + "-" + next);
dfs(i + 1, prev * next, curr - prev + prev * next, path + "*" + next);
}
}
}
}
// Accepted solution for LeetCode #282: Expression Add Operators
// Auto-generated Go example from java.
func exampleSolution() {
}
// Reference (java):
// // Accepted solution for LeetCode #282: Expression Add Operators
// class Solution {
// private List<String> ans;
// private String num;
// private int target;
//
// public List<String> addOperators(String num, int target) {
// ans = new ArrayList<>();
// this.num = num;
// this.target = target;
// dfs(0, 0, 0, "");
// return ans;
// }
//
// private void dfs(int u, long prev, long curr, String path) {
// if (u == num.length()) {
// if (curr == target) ans.add(path);
// return;
// }
// for (int i = u; i < num.length(); i++) {
// if (i != u && num.charAt(u) == '0') {
// break;
// }
// long next = Long.parseLong(num.substring(u, i + 1));
// if (u == 0) {
// dfs(i + 1, next, next, path + next);
// } else {
// dfs(i + 1, next, curr + next, path + "+" + next);
// dfs(i + 1, -next, curr - next, path + "-" + next);
// dfs(i + 1, prev * next, curr - prev + prev * next, path + "*" + next);
// }
// }
// }
// }
# Accepted solution for LeetCode #282: Expression Add Operators
class Solution:
def addOperators(self, num: str, target: int) -> List[str]:
ans = []
def dfs(u, prev, curr, path):
if u == len(num):
if curr == target:
ans.append(path)
return
for i in range(u, len(num)):
if i != u and num[u] == '0':
break
next = int(num[u : i + 1])
if u == 0:
dfs(i + 1, next, next, path + str(next))
else:
dfs(i + 1, next, curr + next, path + "+" + str(next))
dfs(i + 1, -next, curr - next, path + "-" + str(next))
dfs(
i + 1,
prev * next,
curr - prev + prev * next,
path + "*" + str(next),
)
dfs(0, 0, 0, "")
return ans
// Accepted solution for LeetCode #282: Expression Add Operators
struct Solution;
impl Solution {
fn add_operators(num: String, target: i32) -> Vec<String> {
let mut res = vec![];
for i in 1..=num.len() {
let expr = &num[0..i];
let val = expr.parse::<i64>().unwrap();
if expr.len() > 1 && &expr[0..1] == "0" {
break;
}
Self::dfs(
i,
expr.to_string(),
val,
val,
'#',
&mut res,
&num,
target as i64,
);
}
res
}
fn dfs(
start: usize,
expr: String,
val: i64,
prev_val: i64,
prev_op: char,
all: &mut Vec<String>,
num: &str,
target: i64,
) {
if start == num.len() {
if val == target {
all.push(expr);
}
} else {
for end in start + 1..=num.len() {
let cur_expr = &num[start..end];
let cur_val = cur_expr.parse::<i64>().unwrap();
if cur_expr.len() > 1 && &cur_expr[0..1] == "0" {
break;
}
Self::dfs(
end,
format!("{}+{}", expr, cur_expr),
val + cur_val,
cur_val,
'+',
all,
num,
target,
);
Self::dfs(
end,
format!("{}-{}", expr, cur_expr),
val - cur_val,
cur_val,
'-',
all,
num,
target,
);
Self::dfs(
end,
format!("{}*{}", expr, cur_expr),
match prev_op {
'+' => val - prev_val + prev_val * cur_val,
'-' => val + prev_val - prev_val * cur_val,
_ => prev_val * cur_val,
},
prev_val * cur_val,
prev_op,
all,
num,
target,
)
}
}
}
}
#[test]
fn test() {
let num = "123".to_string();
let target = 6;
let mut res = vec_string!["1+2+3", "1*2*3"];
let mut ans = Solution::add_operators(num, target);
res.sort();
ans.sort();
assert_eq!(ans, res);
let num = "232".to_string();
let target = 8;
let mut res = vec_string!["2*3+2", "2+3*2"];
let mut ans = Solution::add_operators(num, target);
res.sort();
ans.sort();
assert_eq!(ans, res);
let num = "105".to_string();
let target = 5;
let mut res = vec_string!["1*0+5", "10-5"];
let mut ans = Solution::add_operators(num, target);
res.sort();
ans.sort();
assert_eq!(ans, res);
let num = "00".to_string();
let target = 0;
let mut res = vec_string!["0+0", "0-0", "0*0"];
let mut ans = Solution::add_operators(num, target);
res.sort();
ans.sort();
assert_eq!(ans, res);
let num = "3456237490".to_string();
let target = 9191;
let mut res = vec_string![];
let mut ans = Solution::add_operators(num, target);
res.sort();
ans.sort();
assert_eq!(ans, res);
}
// Accepted solution for LeetCode #282: Expression Add Operators
// Auto-generated TypeScript example from java.
function exampleSolution(): void {
}
// Reference (java):
// // Accepted solution for LeetCode #282: Expression Add Operators
// class Solution {
// private List<String> ans;
// private String num;
// private int target;
//
// public List<String> addOperators(String num, int target) {
// ans = new ArrayList<>();
// this.num = num;
// this.target = target;
// dfs(0, 0, 0, "");
// return ans;
// }
//
// private void dfs(int u, long prev, long curr, String path) {
// if (u == num.length()) {
// if (curr == target) ans.add(path);
// return;
// }
// for (int i = u; i < num.length(); i++) {
// if (i != u && num.charAt(u) == '0') {
// break;
// }
// long next = Long.parseLong(num.substring(u, i + 1));
// if (u == 0) {
// dfs(i + 1, next, next, path + next);
// } else {
// dfs(i + 1, next, curr + next, path + "+" + next);
// dfs(i + 1, -next, curr - next, path + "-" + next);
// dfs(i + 1, prev * next, curr - prev + prev * next, path + "*" + next);
// }
// }
// }
// }
Use this to step through a reusable interview workflow for this problem.
Generate every possible combination without any filtering. At each of n positions we choose from up to n options, giving nⁿ total candidates. Each candidate takes O(n) to validate. No pruning means we waste time on clearly invalid partial solutions.
Backtracking explores a decision tree, but prunes branches that violate constraints early. Worst case is still factorial or exponential, but pruning dramatically reduces the constant factor in practice. Space is the recursion depth (usually O(n) for n-level decisions).
Review these before coding to avoid predictable interview regressions.
Wrong move: Temporary multiplications exceed integer bounds.
Usually fails on: Large inputs wrap around unexpectedly.
Fix: Use wider types, modular arithmetic, or rearranged operations.
Wrong move: Mutable state leaks between branches.
Usually fails on: Later branches inherit selections from earlier branches.
Fix: Always revert state changes immediately after recursive call.