Here's the problem
There are n nonnegative integers. We want to add or subtract these numbers appropriately to make our target number. For example, to make the number 3 out of [1, 1, 1, 1, 1], you can use the following five methods:
-1+1+1+1+1 = 3
+1-1+1+1+1 = 3
+1+1-1+1+1 = 3
+1+1+1-1+1 = 3
+1+1+1+1-1 = 3
Write the solution function to return the number of ways to make the target number by adding and subtracting the numbers appropriately when the array numbers, target number and target are given as parameters.
Restrictions
I/O example
numbers: [1,1,1,1,1]
target: 3
return: 5
approach
1
/ \
-1 1
/ \ / \
-1 1 -1 1
-1 1 1 3
found this approach in DFS manner, checking all the cases, either addtion or substraction if the combination of the numbers equals to target number then count.
Code below:
def solution(numbers, target):
total = 0
num_len = len(numbers)
def dfs(index=0):
if index < num_len:
numbers[index] *= 1
print('positive / index', index, numbers)
dfs(index + 1)
numbers[index] *= -1
print('negative / index', index, numbers)
dfs(index + 1)
else:
if sum(numbers) == target:
nonlocal total
total += 1
print('matched / index', index, numbers)
dfs()
return total
However, I was wondering how it runs so did console logging.
positive / index 0 [1, 1, 1, 1, 1]
positive / index 1 [1, 1, 1, 1, 1]
positive / index 2 [1, 1, 1, 1, 1]
positive / index 3 [1, 1, 1, 1, 1]
positive / index 4 [1, 1, 1, 1, 1]
negative / index 4 [1, 1, 1, 1, -1]
matched / index 5 [1, 1, 1, 1, -1]
negative / index 3 [1, 1, 1, -1, -1] ### how come this index all of sudden becomes 3? ###
positive / index 4 [1, 1, 1, -1, -1]
...
I kind of understand increment of the index recursively til matched / index 5 but not too sure why right next time it becomes 3.
The logging format may be confusing you. After 5, there are no more recursive calls to be made so the next printed line is associated with an older stack frame that's been sitting waiting for its children to resolve before exploring the next recursive call chain.
If you add indentation you'll see the parent-children relationships more clearly:
print(" " * index + 'positive', numbers)
0 1 2 3 4 5 stack depth
===========================
positive [1, 1, 1, 1, 1]
positive [1, 1, 1, 1, 1]
positive [1, 1, 1, 1, 1]
positive [1, 1, 1, 1, 1]
positive [1, 1, 1, 1, 1]
negative [1, 1, 1, 1, -1]
matched [1, 1, 1, 1, -1]
negative [1, 1, 1, -1, -1] <-- here's the call you asked about
... calls continue ...
Here, you can see that the negative branch your question is about is back in depth 3 and isn't a child of matched
. After the matched
call, there are no more child nodes to explore and the stack pops back to the parent, which also has no further nodes to explore and pops back to its parent at depth 2, which still has its negative
child call chain to explore, which it does, spawning its second call to depth 3.