Need help recursion explanation Leetcode - recursion

How does this code work? (leetcode 95 question) I don't understand how the 2 recursions work inside the for loop. Does the 2nd inner for loop end when the recursive function returns NULL? Or would it continue executing the 3rd inner for loop?
class Solution {
public:
vector<TreeNode*> generateTrees(int n) {
if(n == 0) {
return {};
}
vector<TreeNode*> ans = generateT(1,n);
return ans;
}
vector<TreeNode*> generateT(int l, int r) {
if(l > r) return {nullptr};
vector<TreeNode*> ans;
for(int i=l; i <= r; ++i) {
for(TreeNode*left: generateT(l, i-1)) {
for(TreeNode* right:generateT(i+1, r)) {
ans.push_back(new TreeNode(i));
ans.back()->left = left;
ans.back()->right = right;
}
}
}
return ans;
}
};
Problem statement:
Given an integer n, return all the structurally unique BST's (binary search trees), which has exactly n nodes of unique values from 1 to n. Return the answer in any order.

Does the 2nd inner for loop end when the recursive function returns NULL?
No. The recursive function is not returing NULL, it is returning vector of nullptr.
Or would it continue executing the 3rd inner for loop?
Of course, it will.
How does this code work? I don't understand how the 2 recursions work inside the loop.
I suppose the following snippet is the cause of confusion, so commented the case when nullptr provided by outer loop.
vector<TreeNode*> generateT(int l, int r) {
if(l > r) return { nullptr };
vector<TreeNode*> ans;
for ( int i = l; i <= r; i++ ) {
// if l = 0, i = 0
for ( TreeNode* left :generateT(l, i-1) ) // if l = 0, i = -1, returns { nullptr } (vector of nullptr)
for (TreeNode* right :generateT(i+1, r)) { // now this snippet will execute
auto node = new TreeNode(i);
ans.push_back(node);
node->left = left; // the nullptr we have from the outer loop, will provide null value for this
node->right = right;
}
}
return ans;
}
Visually, for a combination of node where,
a
\
b
/ \
null c
/
null
the above pattern occurs the provided { nullptr } from outer loop will come in handy setting left node.

Related

Climbing Stairs Problem ( Access of element in vector )

Below is a code for the problem of CLIMBING STAIRS https://leetcode.com/problems/climbing-stairs/
class Solution {
public:
int climbStairs(int n) {
vector<int> dp(n,0);
dp[0] = 1;
dp[1] = 2;
for(int i=2;i<n;i++){
dp[i] = dp[i-2]+dp[i-1];
}
return dp[n-1];
}
};
The code gives a RUNTIME ERROR of HEAP BUFFER OVERFLOW.
Looking at the code , if n==1 the code should return dp[n-1] i.e. dp[0] ,
but that does not seem to be the case.
I'm guessing the issue maybe related to access of elements in vector.
Can anyone please explain what could be the issue here ??
if n==1 the code should return dp[n-1] i.e. dp[0] , but that does not seem to be the case.
Yes.
But when n == 1, you call
dp[1] = 2;
so you access the second element when you have only one element.
And what about the case n <= 0 ?
So, maybe
int climbStairs(int n) {
if ( 0 >= 0 ) {
return ???;
} else if ( 1 == n ) {
return 1;
} else {
vector<int> dp(n,0);
dp[0] = 1;
dp[1] = 2;
for(int i=2;i<n;i++){
dp[i] = dp[i-2]+dp[i-1];
}
return dp[n-1];
}
}
The problem states the constraints are
1 <= n <= 45
You're going out of range when n is 1 (i.e. you only have dp[0] that scenario)

Counting the number

I have got a code that generates all possible correct strings of balanced brackets. So if the input is n = 4 there should be 4 brackets in the string and thus the answers the code will give are: {}{} and
{{}}.
Now, what I would like to do is print the number of possible strings. For example, for n = 4 the outcome would be 2.
Given my code, is this possible and how would I make that happen?
Just introduce a counter.
// Change prototype to return the counter
int findBalanced(int p,int n,int o,int c)
{
static char str[100];
// The counter
static int count = 0;
if (c == n) {
// Increment it on every printout
count ++;
printf("%s\n", str);
// Just return zero. This is not used anyway and will give
// Correct result for n=0
return 0;
} else {
if (o > c) {
str[p] = ')';
findBalanced(p + 1, n, o, c + 1);
}
if (o < n) {
str[p] = '(';
findBalanced(p + 1, n, o + 1, c);
}
}
// Return it
return count;
}
What you're looking for is the n-th Catalan number. You'll need to implement binomial coefficient to calculate it, but that's pretty much it.

Constructing a Sparse Tropical Limit Function in Chapel

Given matrices A and B the tropical product is defined to be the usual matrix product with multiplication traded out for addition and addition traded out for minimum. That is, it returns a new matrix C such that,
C_ij = minimum(A_ij, B_ij, A_i1 + B_1j, A_i2 + B_12,..., A_im + B_mj)
Given the underlying adjacency matrix A_g of a graph g, the nth "power" with respect to the tropical product represents the connections between nodes reachable in at most n steps. That is, C_ij = (A**n)_ij has value m if nodes i and j are separated by m<=n edges.
In general, given some graph with N nodes. The diameter of the graph can only be at most N; and, given a graph with diameter k, A**n = A**k for all n>k and the matrix D_ij = A**k is called the "distance matrix" entries representing the distances between all nodes in the graph.
I have written a tropical product function in chapel and I want to write a function that takes an adjacency matrix and returns the resulting distance matrix. I have tried the following approaches to no avail. Guidance in getting past these errors would be greatly appreciated!
proc tropicLimit(A:[] real,B:[] real) {
var R = tropic(A,B);
if A == R {
return A;
} else {
tropicLimit(R,B);
}
}
which threw a domain mismatch error so I made the following edit:
proc tropicLimit(A:[] real,B:[] real) {
var R = tropic(A,B);
if A.domain == R.domain {
if && reduce (A == R) {
return R;
} else {
tropicLimit(R,B);
}
} else {
tropicLimit(R,B);
}
}
which throws
src/MatrixOps.chpl:602: error: control reaches end of function that returns a value
proc tropicLimit(A:[] real,B:[] real) {
var R = tropic(A,B);
if A.domain == R.domain {
if && reduce (A == R) { // Line 605 is this one
} else {
tropicLimit(R,B);
}
} else {
tropicLimit(R,B);
}
return R;
}
Brings me back to this error
src/MatrixOps.chpl:605: error: halt reached - Sparse arrays can't be zippered with anything other than their domains and sibling arrays (CS layout)
I also tried using a for loop with a break condition but that didn't work either
proc tropicLimit(B:[] real) {
var R = tropic(B,B);
for n in B.domain.dim(2) {
var S = tropic(R,B);
if S.domain != R.domain {
R = S; // Intended to just reassign the handle "R" to the contents of "S" i.o.w. destructive update of R
} else {
break;
}
}
return R;
}
Any suggestions?
src/MatrixOps.chpl:605: error: halt reached - Sparse arrays can't be zippered with anything other than their domains and sibling arrays (CS layout)
I believe you are encountering a limitation of zippering sparse arrays in the current implementation, documented in #6577.
Removing some unknowns from the equation, I believe this distilled code snippet demonstrates the issue you are encountering:
use LayoutCS;
var dom = {1..10, 1..10};
var Adom: sparse subdomain(dom) dmapped CS();
var Bdom: sparse subdomain(dom) dmapped CS();
var A: [Adom] real;
var B: [Bdom] real;
Adom += (1,1);
Bdom += (1,1);
A[1,1] = 1.0;
B[1,1] = 2.0;
writeln(A.domain == B.domain); // true
var willThisWork = && reduce (A == B);
// dang.chpl:19: error: halt reached - Sparse arrays can't be zippered with
// anything other than their domains and sibling arrays (CS layout)
As a work-around, I would suggest looping over the sparse indices after confirming the domains are equal and performing a && reduce. This is something you could wrap in a helper function, e.g.
proc main() {
var dom = {1..10, 1..10};
var Adom: sparse subdomain(dom) dmapped CS();
var Bdom: sparse subdomain(dom) dmapped CS();
var A: [Adom] real;
var B: [Bdom] real;
Adom += (1,1);
Bdom += (1,1);
A[1,1] = 1.0;
B[1,1] = 2.0;
if A.domain == B.domain {
writeln(equal(A, B));
}
}
/* Some day, this should be A.equals(B) ! */
proc equal(A: [], B: []) {
// You could also return 'false' if domains do not match
assert(A.domain == B.domain);
var s = true;
forall (i,j) in A.domain with (&& reduce s) {
s &&= (A[i,j] == B[i,j]);
}
return s;
}
src/MatrixOps.chpl:602: error: control reaches end of function that returns a value
This error is a result of not returning something in every condition. I believe you intended to do:
proc tropicLimit(A:[] real,B:[] real) {
var R = tropic(A,B);
if A.domain == R.domain {
if && reduce (A == R) {
return R;
} else {
return tropicLimit(R,B);
}
} else {
return tropicLimit(R,B);
}
}

2 things that I am confused about tail recursion

I've several confusion about tail recursion as follows:
some of the recursion functions are void functions for example,
// Prints the given number of stars on the console.
// Assumes n >= 1.
void printStars(int n) {
if (n == 1) {
// n == 1, base case
cout << "*";
} else {
// n > 1, recursive case
cout << "*"; // print one star myself
printStars(n - 1); // recursion to do the rest
}
}
and another example:
// Prints the given integer's binary representation.
// Precondition: n >= 0
void printBinary(int n) {
if (n < 2) {
// base case; same as base 10
cout << n;
} else {
// recursive case; break number apart
printBinary(n / 2);
printBinary(n % 2);
}
}
As we know by definition tail recursion should return some value from tail call. But for void functions it does not return any value. By intinction I think they are tail recursion but I am not confident about it.
another question is that, if a recursion function has several logical end, should tail recursion come at all logical ends or just one of the logical ends? I saw someone argued that only one of the logical ends is OK, but I am not sure about that. Here's my example:
// Returns base ^ exp.
// Precondition: exp >= 0
int power(int base, int exp) {
if (exp < 0) {
throw "illegal negative exponent";
} else if (exp == 0) {
// base case; any number to 0th power is 1
return 1;
} else if (exp % 2 == 0) {
// recursive case 1: x^y = (x^2)^(y/2)
return power(base * base, exp / 2);
} else {
// recursive case 2: x^y = x * x^(y-1)
return base * power(base, exp - 1);
}
}
Here we have logical end as tail recursion and another one that is not tail recursion. Do you think this function is tail recursion or not? why?

Are there any example of Mutual recursion?

Are there any examples for a recursive function that calls an other function which calls the first one too ?
Example :
function1()
{
//do something
function2();
//do something
}
function2()
{
//do something
function1();
//do something
}
Mutual recursion is common in code that parses mathematical expressions (and other grammars). A recursive descent parser based on the grammar below will naturally contain mutual recursion: expression-terms-term-factor-primary-expression.
expression
+ terms
- terms
terms
terms
term + terms
term - terms
term
factor
factor * term
factor / term
factor
primary
primary ^ factor
primary
( expression )
number
name
name ( expression )
The proper term for this is Mutual Recursion.
http://en.wikipedia.org/wiki/Mutual_recursion
There's an example on that page, I'll reproduce here in Java:
boolean even( int number )
{
if( number == 0 )
return true;
else
return odd(abs(number)-1)
}
boolean odd( int number )
{
if( number == 0 )
return false;
else
return even(abs(number)-1);
}
Where abs( n ) means return the absolute value of a number.
Clearly this is not efficient, just to demonstrate a point.
An example might be the minmax algorithm commonly used in game programs such as chess. Starting at the top of the game tree, the goal is to find the maximum value of all the nodes at the level below, whose values are defined as the minimum of the values of the nodes below that, whose values are defines as the maximum of the values below that, whose values ...
I can think of two common sources of mutual recursion.
Functions dealing with mutually recursive types
Consider an Abstract Syntax Tree (AST) that keeps position information in every node. The type might look like this:
type Expr =
| Int of int
| Var of string
| Add of ExprAux * ExprAux
and ExprAux = Expr of int * Expr
The easiest way to write functions that manipulate values of these types is to write mutually recursive functions. For example, a function to find the set of free variables:
let rec freeVariables = function
| Int n -> Set.empty
| Var x -> Set.singleton x
| Add(f, g) -> Set.union (freeVariablesAux f) (freeVariablesAux g)
and freeVariablesAux (Expr(loc, e)) =
freeVariables e
State machines
Consider a state machine that is either on, off or paused with instructions to start, stop, pause and resume (F# code):
type Instruction = Start | Stop | Pause | Resume
The state machine might be written as mutually recursive functions with one function for each state:
type State = State of (Instruction -> State)
let rec isOff = function
| Start -> State isOn
| _ -> State isOff
and isOn = function
| Stop -> State isOff
| Pause -> State isPaused
| _ -> State isOn
and isPaused = function
| Stop -> State isOff
| Resume -> State isOn
| _ -> State isPaused
It's a bit contrived and not very efficient, but you could do this with a function to calculate Fibbonacci numbers as in:
fib2(n) { return fib(n-2); }
fib1(n) { return fib(n-1); }
fib(n)
{
if (n>1)
return fib1(n) + fib2(n);
else
return 1;
}
In this case its efficiency can be dramatically enhanced if the language supports memoization
In a language with proper tail calls, Mutual Tail Recursion is a very natural way of implementing automata.
Here is my coded solution. For a calculator app that performs *,/,- operations using mutual recursion. It also checks for brackets (()) to decide the order of precedence.
Flow:: expression -> term -> factor -> expression
Calculator.h
#ifndef CALCULATOR_H_
#define CALCULATOR_H_
#include <string>
using namespace std;
/****** A Calculator Class holding expression, term, factor ********/
class Calculator
{
public:
/**Default Constructor*/
Calculator();
/** Parameterized Constructor common for all exception
* #aparam e exception value
* */
Calculator(char e);
/**
* Function to start computation
* #param input - input expression*/
void start(string input);
/**
* Evaluates Term*
* #param input string for term*/
double term(string& input);
/* Evaluates factor*
* #param input string for factor*/
double factor(string& input);
/* Evaluates Expression*
* #param input string for expression*/
double expression(string& input);
/* Evaluates number*
* #param input string for number*/
string number(string n);
/**
* Prints calculates value of the expression
* */
void print();
/**
* Converts char to double
* #param c input char
* */
double charTONum(const char* c);
/**
* Get error
*/
char get_value() const;
/** Reset all values*/
void reset();
private:
int lock;//set lock to check extra parenthesis
double result;// result
char error_msg;// error message
};
/**Error for unexpected string operation*/
class Unexpected_error:public Calculator
{
public:
Unexpected_error(char e):Calculator(e){};
};
/**Error for missing parenthesis*/
class Missing_parenthesis:public Calculator
{
public:
Missing_parenthesis(char e):Calculator(e){};
};
/**Error if divide by zeros*/
class DivideByZero:public Calculator{
public:
DivideByZero():Calculator(){};
};
#endif
===============================================================================
Calculator.cpp
//============================================================================
// Name : Calculator.cpp
// Author : Anurag
// Version :
// Copyright : Your copyright notice
// Description : Calculator using mutual recursion in C++, Ansi-style
//============================================================================
#include "Calculator.h"
#include <iostream>
#include <string>
#include <math.h>
#include <exception>
using namespace std;
Calculator::Calculator():lock(0),result(0),error_msg(' '){
}
Calculator::Calculator(char e):result(0), error_msg(e) {
}
char Calculator::get_value() const {
return this->error_msg;
}
void Calculator::start(string input) {
try{
result = expression(input);
print();
}catch (Unexpected_error e) {
cout<<result<<endl;
cout<<"***** Unexpected "<<e.get_value()<<endl;
}catch (Missing_parenthesis e) {
cout<<"***** Missing "<<e.get_value()<<endl;
}catch (DivideByZero e) {
cout<<"***** Division By Zero" << endl;
}
}
double Calculator::expression(string& input) {
double expression=0;
if(input.size()==0)
return 0;
expression = term(input);
if(input[0] == ' ')
input = input.substr(1);
if(input[0] == '+') {
input = input.substr(1);
expression += term(input);
}
else if(input[0] == '-') {
input = input.substr(1);
expression -= term(input);
}
if(input[0] == '%'){
result = expression;
throw Unexpected_error(input[0]);
}
if(input[0]==')' && lock<=0 )
throw Missing_parenthesis(')');
return expression;
}
double Calculator::term(string& input) {
if(input.size()==0)
return 1;
double term=1;
term = factor(input);
if(input[0] == ' ')
input = input.substr(1);
if(input[0] == '*') {
input = input.substr(1);
term = term * factor(input);
}
else if(input[0] == '/') {
input = input.substr(1);
double den = factor(input);
if(den==0) {
throw DivideByZero();
}
term = term / den;
}
return term;
}
double Calculator::factor(string& input) {
double factor=0;
if(input[0] == ' ') {
input = input.substr(1);
}
if(input[0] == '(') {
lock++;
input = input.substr(1);
factor = expression(input);
if(input[0]==')') {
lock--;
input = input.substr(1);
return factor;
}else{
throw Missing_parenthesis(')');
}
}
else if (input[0]>='0' && input[0]<='9'){
string nums = input.substr(0,1) + number(input.substr(1));
input = input.substr(nums.size());
return stod(nums);
}
else {
result = factor;
throw Unexpected_error(input[0]);
}
return factor;
}
string Calculator::number(string input) {
if(input.substr(0,2)=="E+" || input.substr(0,2)=="E-" || input.substr(0,2)=="e-" || input.substr(0,2)=="e-")
return input.substr(0,2) + number(input.substr(2));
else if((input[0]>='0' && input[0]<='9') || (input[0]=='.'))
return input.substr(0,1) + number(input.substr(1));
else
return "";
}
void Calculator::print() {
cout << result << endl;
}
void Calculator::reset(){
this->lock=0;
this->result=0;
}
int main() {
Calculator* cal = new Calculator;
string input;
cout<<"Expression? ";
getline(cin,input);
while(input!="."){
cal->start(input.substr(0,input.size()-2));
cout<<"Expression? ";
cal->reset();
getline(cin,input);
}
cout << "Done!" << endl;
return 0;
}
==============================================================
Sample input-> Expression? (42+8)*10 =
Output-> 500
Top down merge sort can use a pair of mutually recursive functions to alternate the direction of merge based on level of recursion.
For the example code below, a[] is the array to be sorted, b[] is a temporary working array. For a naive implementation of merge sort, each merge operation copies data from a[] to b[], then merges b[] back to a[], or it merges from a[] to b[], then copies from b[] back to a[]. This requires n ยท ceiling(log2(n)) copy operations. To eliminate the copy operations used for merging, the direction of merge can be alternated based on level of recursion, merge from a[] to b[], merge from b[] to a[], ..., and switch to in place insertion sort for small runs in a[], as insertion sort on small runs is faster than merge sort.
In this example, MergeSortAtoA() and MergeSortAtoB() are the mutually recursive functions.
Example java code:
static final int ISZ = 64; // use insertion sort if size <= ISZ
static void MergeSort(int a[])
{
int n = a.length;
if(n < 2)
return;
int [] b = new int[n];
MergeSortAtoA(a, b, 0, n);
}
static void MergeSortAtoA(int a[], int b[], int ll, int ee)
{
if ((ee - ll) <= ISZ){ // use insertion sort on small runs
InsertionSort(a, ll, ee);
return;
}
int rr = (ll + ee)>>1; // midpoint, start of right half
MergeSortAtoB(a, b, ll, rr);
MergeSortAtoB(a, b, rr, ee);
Merge(b, a, ll, rr, ee); // merge b to a
}
static void MergeSortAtoB(int a[], int b[], int ll, int ee)
{
int rr = (ll + ee)>>1; // midpoint, start of right half
MergeSortAtoA(a, b, ll, rr);
MergeSortAtoA(a, b, rr, ee);
Merge(a, b, ll, rr, ee); // merge a to b
}
static void Merge(int a[], int b[], int ll, int rr, int ee)
{
int o = ll; // b[] index
int l = ll; // a[] left index
int r = rr; // a[] right index
while(true){ // merge data
if(a[l] <= a[r]){ // if a[l] <= a[r]
b[o++] = a[l++]; // copy a[l]
if(l < rr) // if not end of left run
continue; // continue (back to while)
while(r < ee){ // else copy rest of right run
b[o++] = a[r++];
}
break; // and return
} else { // else a[l] > a[r]
b[o++] = a[r++]; // copy a[r]
if(r < ee) // if not end of right run
continue; // continue (back to while)
while(l < rr){ // else copy rest of left run
b[o++] = a[l++];
}
break; // and return
}
}
}
static void InsertionSort(int a[], int ll, int ee)
{
int i, j;
int t;
for (j = ll + 1; j < ee; j++) {
t = a[j];
i = j-1;
while(i >= ll && a[i] > t){
a[i+1] = a[i];
i--;
}
a[i+1] = t;
}
}

Resources