how to rewrite the recursive solution to iterative one - recursion

The problem is derive from OJ.
The description is :
We are playing the Guess Game. The game is as follows:
I pick a number from 1 to n. You have to guess which number I picked.
Every time you guess wrong, I'll tell you whether the number I picked is higher or lower.
However, when you guess a particular number x, and you guess wrong, you pay $x. You win the game when you guess the number I picked.
Given a particular n ≥ 1, find out how much money you need to have to guarantee a win.
I write small snippet about MinMax problem in recursion. But it is slow and I want to rewrite it in a iterative way. Could anyone help with that and give me the idea about how you convert the recursive solution to iterative one? Any idea is appreciated. The code is showed below:
public int getMoneyAmount(int n) {
int[][] dp = new int[n + 1][n + 1];
for(int i = 0; i < dp.length; i++)
Arrays.fill(dp[i], -1);
return solve(dp, 1, n);
}
private int solve(int[][] dp, int left, int right){
if(left >= right){
return 0;
}
if(dp[left][right] != -1){
return dp[left][right];
}
dp[left][right] = Integer.MAX_VALUE;
for(int i = left; i <= right; i++){
dp[left][right] = Math.min(dp[left][right], i + Math.max(solve(dp, left, i - 1),solve(dp, i + 1, right)));
}
return dp[left][right];
}

In general, you convert using some focused concepts:
Replace the recursion with a while loop -- or a for loop, if you can pre-determine how many iterations you need (which you can do in this case).
Within the loop, check for the recursion's termination conditions; when you hit one of those, skip the rest of the loop.
Maintain local variables to replace the parameters and return value.
The loop termination is completion of the entire problem. In your case, this would be filling out the entire dp array.
The loop body consists of the computations that are currently in your recursion step: preparing the arguments for the recursive call.
Your general approach is to step through a nested (2-D) loop to fill out your array, starting from the simplest cases (left = right) and working your way to the far corner (left = 1, right = n). Note that your main diagonal is 0 (initialize that before you get into the loop), and your lower triangle is unused (don't even bother to initialize it).
For the loop body, you should be able to derive how to fill in each succeeding diagonal (one element shorter in each iteration) from the one you just did. That assignment statement is the body. In this case, you don't need the recursion termination conditions: the one that returns 0 is what you cover in initialization; the other you never hit, controlling left and right with your loop indices.
Are these enough hints to get you moving?

Related

In this code can you please explain what is happening after the draw(n -1) function

#include <stdio.h>
#include <cs50.h>
void draw(int n);
int main(void)
{
int height = get_int("number:");
draw(height);
}
void draw(int n)
{
if(n <= 0)
{
return;
}
draw(n - 1);
for(int i = 0 ; i < n ; i++)
{
printf("#");
}
printf("\n");
}
Iam learing recursion topic, suppose the user input 4 when the compiler completes the if part the value of n is '0' and returning when i debug , but then the for loop starts the value of 'n' becomes '1' and also 'i' doesn't change it constantly 0 why is that iam expected n becomes 0 after the if draw(n - 1) completes.
I will try to make this explanation as simple as I can. First things first, To begin with, when using recursion, you would be noticing the calling of a method within itself with a different argument. In your case it is the draw method.
Now each time, a draw method is called inside another draw method, the outer method(in this case the draw that is called first) stops its flow of execution till the completion of the inner draw.
So when you called draw(4), it ran all the code till it reached line 5 in draw method, and called draw(3). Your for loop of draw(4) is not executed yet. This will continue till draw(1) calls a draw(0). At this stage, draw(0) will return out and the draw(1) will continue its for loop from where it left. So you would find that here n=1, leading to the first print of # and then a new line after it. Once the operation completes in here, it continues with where it left for draw(2). Which is the for loop in draw(2) where the value of n=2. And here it does two print of # and then a new line. This continues.
Now for the question why i is always 0, it is to do with what we call scopes in programming, you can see that each time the i is declared fresh in the loop and assigned a value 0. This means, each time a for loop is hit, the value of i is reinitialised to 0. If you had a global var i out side of your draw method, you would have had the value of i being retained.
I did try my best to put things in as simple form as possible but feel free to let me know if you needed more clarity.

Calculating number of nodes in BST using recursion c++

I'm trying to find the number of nodes in a BST using recursion. Here is my code
struct Node{
int key;
struct Node* left;
struct Node* right;
Node(){
int key = 0;
struct Node* left = nullptr;
struct Node* right = nullptr;
}
};
src_root is the address of the root node of the tree.
int BST::countNodes(Node* src_root, int sum){
if((src_root==root && src_root==nullptr) || src_root==nullptr)
return 0;
else if(src_root->left==nullptr || src_root->right==nullptr)
return sum;
return countNodes(src_root->left, sum + 1) + countNodes(src_root->right, sum + 1) + 1;
}
However my code only seems to work if there are 3 nodes. Anything greater than 3 gives wrong answer. Please help me find out what's wrong with it. Thanks!
It is a long time ago since I made anything in C/C++ so if there might be some syntax errors.
int BST::countNodes(Node *scr_root)
{
if (scr_root == null) return 0;
return 1 + countNodes(scr_root->left) + countNodes(scr_root->right);
}
I think that will do the job.
You have several logical and structural problems in your implementation. Casperah gave you the "clean" answer that I assume you already found on the web (if you haven't already done that research, you shouldn't have posted your question). Thus, what you're looking for is not someone else's solution, but how to fix your own.
Why do you pass sum down the tree? Lower nodes shouldn't care what the previous count is; it's the parent's job to accumulate the counts from its children. See how that's done in Casperah's answer? Drop the extra parameter from your code; it's merely another source for error.
Your base case has an identically false clause: src_root==root && src_root==nullptr ... if you make a meaningful call, src_root cannot be both root and nullptr.
Why are you comparing against a global value, root? Each call simply gets its own job done and returns. When your call tree crawls back to the original invocation, the one that was called with the root, it simply does its job and returns to the calling program. This should not be a special case.
Your else clause is wrong: it says that if either child is null, you ignore counting the other child altogether and return only the count so far. This guarantees that you'll give the wrong answer unless the tree is absolutely balanced and filled, a total of 2^N - 1 nodes for N levels.
Fix those items in whatever order you find instructive; the idea is to learn. Note, however, that your final code should look a lot like the answer Casperah provided.

Understanding Recursion with Merge sort

I see some of the posts to understand merge sort. I know recursive methods maintains stack to hold values. (my understand was return statement result will be in stack )
private int recur(int count) {
if (count > 0) {
System.out.println(count);
return count + recur(--count); // this value will be in stack.
}
return count;
}
I am confusing in merge sort how stack is maintaining here.
private void divide(int low, int high) {
System.out.println("Divide => Low: "+ low +" High: "+ high);
if (low < high) {
int middle = (low + high) / 2;
divide(low, middle); // {0,7},{0,3}, {0,1} ;
divide(middle + 1, high); // {0,0}; high = 1; // 2nd divide
combine(low, middle, high);
}
}
Is stack for all local variables?
When 2nd recursive method calls, 1st recursive will also join?
How stack are maintained in such cases?
You only have to know that a statement needs to finish and return and that you call divide or combine from divide works the same. Both need to finish before the next line of code can be executed or, if there are no more lines, the function returns. Yes, it's done with stack but it's really not important.
The state of the waiters variables low, high and middle is only the current invocations bindings so they don't get mixed with other invocations.
Every time you nest a new call it gets it's own variables and each need to finish. When the low-middle is finished it calls middle+1-high and when that finished combine. Those calls will do the same so you will have deeper nesting and how the call structure will be visited is like like a binary tree structure with the leafs being low == high (one element).
A word of advice. When looking at recursive code try doing it from leaf to more complex tree. eg. try it out with base case first, then the simplest of default case. eg.
1 element array: does nothing
2 element array: -> 1 element array (see 1.), 1 element array, combine
4 element array: -> 2 element array (see 2.), 2 element array, combine
Notice that the 2. you know both recursive calls won't do anything and combine will do perhaps a swap. The 3. does 2. twice (including the swap) before combine that will merge 2 2 element arrays that are sorted. You are perhaps looking at it the other way, which requires you to halt 3. to do 2. that halts it and does 1., then the next 1, then back to 2. to do the text that has two 1s... It needs pen and paper. Looking at it from leaf to root using what you have learned of it so far lets you understand it much easier. I do think functional recursion is easier to grasp than mutating structures like your merge sort. eg. fibonacci sequence.

what is the difference of these two implementations of a recursion algorihtm?

I am doing a leetcode problem.
A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below).
The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below).
How many possible unique paths are there?
So I tried this implementation first and got a "exceeds runtime" (I forgot the exact term but it means the implementation is slow). So I changed it version 2, which use a array to save the results. I honestly don't know how the recursion works internally and why these two implementations have different efficiency.
version 1(slow):
class Solution {
// int res[101][101]={{0}};
public:
int uniquePaths(int m, int n) {
if (m==1 || n==1) return 1;
else{
return uniquePaths(m-1,n) + uniquePaths(m,n-1);
}
}
};
version2 (faster):
class Solution {
int res[101][101]={{0}};
public:
int uniquePaths(int m, int n) {
if (m==1 || n==1) return 1;
else{
if (res[m-1][n]==0) res[m-1][n] = uniquePaths(m-1,n);
if (res[m][n-1]==0) res[m][n-1] = uniquePaths(m,n-1);
return res[m-1][n] + res[m][n-1];
}
}
};
Version 1 is slower beacuse you are calculating the same data again and again. I'll try to explain this on different problem but I guess that you know Fibonacci numbers. You can calculate any Fibonacci number by following recursive algorithm:
fib(n):
if n == 0 then return 0
if n == 1 then return 1
return fib(n-1) + fib(n-1)
But what actually are you calculating? If you want to find fib(5) you need to calculate fib(4) and fib(3), then to calculate fib(4) you need to calculate fib(3) again! Take a look at the image to fully understand:
The same situation is in your code. You compute uniquePaths(m,n) even if you have it calculated before. To avoid that, in your second version you use array to store computed data and you don't have to compute it again when res[m][n]!=0

Usage of Map and Translate Functions in Processing

New to Processing working on understanding this code:
import com.onformative.leap.LeapMotionP5;
import java.util.*;
LeapMotionP5 leap;
LinkedList<Integer> values;
public void setup() {
size(800, 300);
frameRate(120); //Specifies the number of frames to be displayed every second
leap = new LeapMotionP5(this);
values = new LinkedList<Integer>();
stroke(255);
}
int lastY = 0;
public void draw() {
**translate(0, 180)**; //(x, y, z)
background(0);
if (values.size() >= width) {
values.removeFirst();
}
values.add((int) leap.getVelocity(leap.getHand(0)).y);
System.out.println((int) leap.getVelocity(leap.getHand(0)).y);
int counter = 0;
** for (Integer val : values)** {
**val = (int) map(val, 0, 1500, 0, height);**
line(counter, val, counter - 1, lastY);
point(counter, val);
lastY = val;
counter++;
}
** line(0, map(1300, 0, 1500, 0, height), width, map(1300, 0, 1500, 0, height)); //(x1, y1, x2, y2)**
}
It basically draw of graph of movement detected on the y axis using the Leap Motion sensor. Output looks like this:
I eventually need to do something similar to this that would detect amplitude instead of velocity simultaneously on all 3 axis instead of just the y.
The use of Map and Translate are whats really confusing me. I've read the definitions of these functions on the Processing website so I know what they are and the syntax, but what I dont understand is the why?! (which is arguably the most important part.
I am asking if someone can provide simple examples that explain the WHY behind using these 2 functions. For instance, given a program that needs to do A, B, and C, with data foo, y, and x, you would use Map or Translate because A, B, and C.
I think programming guides often overlook this important fact but to me it is very important to truly understanding a function.
Bonus points for explaining:
for (Integer val : values) and LinkedList<Integer> values; (cant find any documentation on the processing website for these)
Thanks!
First, we'll do the easiest one. LinkedList is a data structure similar to ArrayList, which you may be more familiar with. If not, then it's just a list of values (of the type between the angle braces, in this case integer) that you can insert and remove from. It's a bit complicated on the inside, but if it doesn't appear in the Processing documentation, it's a safe bet that it's built into Java itself (java documentation).
This line:
for (Integer val : values)
is called a "for-each" or "foreach" loop, which has plenty of very good explanation on the internet, but I'll give a brief explanation here. If you have some list (perhaps a LinkedList, perhaps an ArrayList, whatever) and want to do something with all the elements, you might do something like this:
for(int i = 0; i < values.size(); i++){
println(values.get(i)); //or whatever
println(values.get(i) * 2);
println(pow(values.get(i),3) - 2*pow(values.get(i),2) + values.get(i));
}
If you're doing a lot of manipulation with each element, it quickly gets tedious to write out values.get(i) each time. The solution would be to capture values.get(i) into some variable at the start of the loop and use that everywhere instead. However, this is not 100% elegant, so java has a built-in way to do this, which is the for-each loop. The code
for (Integer val : values){
//use val
}
is equivalent to
for(int i = 0; i < values.size(); i++){
int val = values.get(i);
//use val
}
Hopefully that makes sense.
map() takes a number in one linear system and maps it onto another linear system. Imagine if I were an evil professor and wanted to give students random grades from 0 to 100. I have a function that returns a random decimal between 0 and 1, so I can now do map(rand(),0,1,0,100); and it will convert the number for me! In this example, you could also just multiply by 100 and get the same result, but it is usually not so trivial. In this case, you have a sensor reading between 0 and 1500, but if you just plotted that value directly, sometimes it would go off the screen! So you have to scale it to an appropriate scale, which is what that does. 1500 is the max that the reading can be, and presumably we want the maximum graphing height to be at the edge of the screen.
I'm not familiar with your setup, but it looks like the readings can be negative, which means that they might get graphed off the screen, too. The better solution would be to map the readings from -1500,1500 to 0,height, but it looks like they chose to do it a different way. Whenever you call a drawing function in processing (eg point(x,y)), it draws the pixels at (x,y) offset from (0,0). Sometimes you don't want it to draw it relative to (0,0), so the translate() function allows you to change what it draws things relative against. In this case, translating allows you to plot some point (x,0) somewhere in the middle of the screen, rather than on the edge.
Hope that helps!

Resources