Reference Document: HW 3.pdf

Recursion Tree

graph TB
    A((N))-->B((N-1))
    A-->C((N-2))
    A-->D((...))
    A-->E((0))
    B-->F((N-2))
    B-->G((N-3))
    B-->H((...))
    B-->I((0))
    C-->J((N-3))
    C-->K((N-4))
    C-->L((...))
    C-->M((0))
    F-->N((N-3))
    F-->O((N-4))
    F-->P((...))
    F-->Q((0))

General Truncated Tree of the above recursion up to 3 levels and left most branch extended
We can see that a number of branches are being repeated

Brute Force Recursive Solution

float C(float N){
	if(N == 0)
		return 1;
 
	float sum=0;
	for(int i=0; i<=N-1; i++)
		sum += C(i);
 
	return 2/N * sum + N;
}

Dynamic Programming

Top Down Recursive Solution

Derivation of Proposed Formula

If we have the value of C(N) we can get its previous cumulative values

So say, if we find C(N-1) we can get previous sum from formula and add those values to get sum for C(N)

float C(float N, float *arr){
	arr[0] = 1;
 
	if(arr[(int) N] == 0.0){
		float prev_n = 0.0, prev_n_cumsum = 0.0;
 
		// Getting the Previous Sum
		prev_n = C(N-1, arr);
 
		// Calculating the cummulative sum before the previous sum
		// Equation derived from given recurrence
		prev_n_cumsum = (prev_n - (N-1)) * (N-1)/2;
 
		float total_sum = prev_n + prev_n_cumsum;
 
		arr[(int) N] = 2/N * total_sum + N;
	}
	return arr[(int) N];
}

Bottom Up Iterative Solution

float C(int N, float *arr){
	// Our Base Case
	arr[0] = 1;
 
	// Since we are iterating from bottom to top, we can directly make use of
	// our memoization
	for(float i=1; i<=N; i++){
		float c_sum = 0;
		for(int j=0; j<i; j++)
			c_sum += arr[j];
 
		arr[(int)i] = ((2/i) * c_sum) + i;
	}
 
	return arr[N];
}