Keep Track Of Global Variable In Recursion
For example if we want to keep track of the max number:
class App:
maxNumber = 0
nums = [9, -9, 0, 1, 3]
# 0, 1, 2, 3, 4
def traverse(self, index, total):
if index >= len(self.nums): return total
self.maxNumber = max(self.maxNumber,
self.traverse(index + 1, total + self.nums[index]),
self.traverse(index + 1, total))
return self.maxNumber
app = App()
app.traverse(0, 0)
print(app.maxNumber)
Which in this case should return 13 because that's the maximum sum that can be created using this array.
Note that if we called like the above (we put the recursion function inside the max()
) then we need to return self.maxNumber
instead of total
.
Why?
Because imagine if we return total. In the subsequent calls the maxNumber
is not updated. For example
def traverse(self, index, total):
if index >= len(self.nums): return total
self.maxNumber = max(self.maxNumber,
self.traverse(index + 1, total + self.nums[index]),
self.traverse(index + 1, total))
return total # HERE
# at index = 0, we call
max(0, traverse(1, 9), ...)
# at index = 1, we call
max(0, traverse(2, 9 - 9), ...)
# at index = 2, we call
max(0, traverse(3, 9 - 9 + 0), ...)
# at index = 3, we call
max(0, traverse(3, 9 - 9 + 0 + 1), ...)
# at index = 4, we call
max(0, traverse(3, 9 - 9 + 0 + 1 + 3), ...)
# at index = 5, we return 9 - 9 + 0 + 1 + 3 = 4
return 4
# now back at index = 4 we have
max(0, 4, traverse(3, 9 - 9 + 0 + 1))
# ok so the maxNumber now is 4, but it will return
# the current total, which is 9 - 9 + 0 + 1 = 1
# now back at index = 3, we have
max(0, 1, traverse(3, 9 - 9 + 0))
# anyways as you can see because maxNumber was not
# updated and we return `1`. So that the maxNumber now
# becomes `1` -- which it should be `4` instead
Solution
Solution 1. Return maxNumber
The solution for that is if we need to return self.maxNumber
instead
def traverse(self, index, total):
if index >= len(self.nums): return total
self.maxNumber = max(self.maxNumber,
self.traverse(index + 1, total + self.nums[index]),
self.traverse(index + 1, total))
return self.maxNumber
by doing this, we're actually updating the maxNumber
. So that the max call looks like below
max(oldMaxNumber, newMaxNumberIfTakeThisNumber, newMaxNumberIfNotTakeThisNumber)
Soluton 2. Store recursion call inside a variable
or if we want to return total
still, we put this into a separate variable
def traverse(self, index, total):
if index >= len(self.nums): return total
takeThisNumber = self.traverse(index + 1, total + self.nums[index])
dontTakeThisNumber = self.traverse(index + 1, total)
self.maxNumber = max(self.maxNumber, takeThisNumber, dontTakeThisNumber)
return total
The reason for this is in the subsequent call, self.maxNumber
will be updated already. Therefore when we reaches
self.maxNumber = max(self.maxNumber, takeThisNumber, dontTakeThisNumber)
The maxNumber
is already updated from the previous call. So for each subsequent call, the function is looking like this:
max(newMaxNumber, totalIfTakeTheNumber, totalIfNotTakeTheNumber)