For cases where recursion is used as well as memoization (so that a number of subtrees of what would otherwise be the overall recursive call tree are each replaced to be O(1)), I am wondering what the resulting runtime is (such as whether it is the same as the corresponding dynamic programming approach), or really, how to calculate it if it is not the same as the corresponding dynamic programming approach?
Example: I am wondering, for this leetcode problem, what the runtime of the following solution would be (courtesy of this solution):
unordered_map<string, int> memo;
int profit(vector<int>& prices, int i, int isBuy, int k){
if(i == prices.size() || k == 2) // return if two transactions are completed
return 0;
string key = to_string(i) + "-" + to_string(isBuy) + "-" + to_string(k);
if(memo.find(key)!=memo.end())
return memo[key];
int a,b;
if(isBuy){ // if isBuy is 1, we have a choice to purchase the stock
a = profit(prices, i + 1, 1, k); // do not buy
b = profit(prices, i + 1, 0, k) - prices[i]; // buy and add the cost
}
else{ // if isBuy is 0, we can only sell as we have already bought
a = profit(prices, i + 1, 0, k); // do not sell
b = profit(prices, i + 1, 1, k + 1) + prices[i]; // sell and add the profit
}
return memo[key] = max(a, b); // best choice among trading and skipping
}
int maxProfit(vector<int>& prices) {
return profit(prices, 0, 1, 0);
}
For instance, is the runtime here O(n * 2 * k) = O(nk) here, where n = prices.size(), 2 for whether is a buy or sell, and k for the number of possible times we can buy or sell (I know it's 2 here, so really O(n) overall)?
My question is mainly because recursion with memoization, though it may make a certain subtree of recursive calls become O(1), still can have that subtree occur multiple times in the overall recursive tree of calls; and so I'm wondering if this memoization with the recursion really succeeds in bringing the runtime down to what it would be with dynamic programming (ie just arrays/vectors and loops, without recursion), or if because each of those now-O(1) subtree recursive call roots can occur multiple times, it's actually greater than that?