Convert c++ function from recursive to iterations with stack - c++

I'm trying to convert this function from recursive to iterations with stack but I can't figure out how and I keep failing
int F(int n)
{
if (n <= 1) return 1;
int a = n + F(n - 1);
cout << a << endl;
int b = n * F(n / 2);
int c = n - 2 - (a + b) % 2;
int d = F(c);
return a + b + d;
}
I tried to debug the code and break it down but luck was not on my side
edit:
these are the requirements
You are not allowed to use any built-in functions except those from: <cstdlib>, <cstdio>, <cstring>, <iostream> and <stack>.
You are not allowed to use string, vector, or anything from STL libraries except stack.
Moreover, I attempted to make multiple stack for each variable to store the results then substitute the answer but am still working on it.

Let's look at the single parts of the recursion:
We have f(n-1), f(n/2) and f(n-2-[0 or 1], no matter how big a or b might ever get. All these recursive calls fall back to a lower value.
First few values:
f(n) = 1; // n <= 1
f(2) = (2 + f(1)) + (2 * f(1)) + f(-1) // (c = 2 - 2 - 5 % 2)
= 6
f(3) = (3 + f(2)) + (3 * f(1)) + f(1) // (c = 3 - 2 - 12 % 2)
= 13
f(4) = (4 + f(3)) + (4 * f(2)) + f(1) // (c = 4 - 2 - 41 % 2)
= 42
f(5) = (5 + f(4)) + (5 * f(2)) + f(2) // (c = 5 - 2 - 77 % 2)
= 83
Obviously we can calculate a new value based on old ones – and if we calculate these first, we can simply look them up – apart from n == 2 where we'd get a negative lookup index. So we might initialise a std::vector with f(0), f(1) and f(2) (i.e. 1, 1, 6) and then iterate from 3 onwards until n calculating new values based upon the lookups of old ones:
if n <= 1:
return 1;
std::vector v({1, 1, 6});
if n >= v.size():
v.reserve(n + 1); // avoid unnecessary re-allocations
iterate i from v.size() up to n inclusive:
v.push_back(calculate, instead recursive calls look up in vector!);
return v[n];
Optimisation opportunity: If you retain results from previous calculations you don't need to re-calculate the values again and again (for the price of constantly instead of temporarily consuming quite a bit of memory!); all you have to do for is making the vector static:
static std::vector v({1, 1, 6});
// ^^^^^^
Edit – according to the edits of the question (referring to version 4):
As you are not allowed to use std::vector as proposed above instead allocate an array:
auto v = new unsigned int[std::max(3, n + 1)] { 1, 1, 6};
// I personally prefer unsigned int as negative values aren't possible anyway...
// calculate as with the vector
auto result = v[n];
delete[] v;
return result;
Keeping old values for future calls still is possible, but more complicated; you need to remember how large your array is and if n is greater than the size re-allocate a new array, copy values from old one to and delete the latter.
This approach keeps the requirements of the task as using std::stack is not explicitly requested... If that gets enforced then the algorithm won't change – solely the lookup gets pretty ugly; you need in addition to your main stack a temporary one to be able to backup the elements on top of those you want to lookup up:
// lookup the three values in DESCENDING order, each one
// as follows:
while(stack.size() > lookupIndex)
{
backup.push(stack.top());
stack.pop();
}
// now top elements have been moved away from main stack and
// backed up; the element to be looked up is moved, too;
// for illustration: consider lookupIndex == 0; what would be
// the main stack's size after popping the surplus elements???
lookupValue = backup().top();
// now as you have looked up all three values move the elements
// in the backup stack back to the main stack:
while(!backup.empty()) { /* analogously to above */ }
You can spare moving back if you are calculating the final value for n – unless you retain the main stack for future calls analogously to the static vector above (make it static analogously...).
Final note: I think more than anything else you can learn from this example how much additional effort – in coding and in runtime – you will load upon your shoulders if you chose a bad data structure compared to having chosen a suitable one...

Consider that
F(n) = 1 for all n <= 1, especially
F(0) = 1 and F(1) = 1
This is basically all you need to get the solution with a loop:
int F2(int n) {
std::vector<int> F{1,1};
for (int i=2;i <= n; ++i) {
int a = i + F[i-1];
int b = i * F[i/2];
int x = i-2-(a+b)%2; // might be negative
int d = x>0 ? F[x] : 1;
F.push_back(a+b+d);
}
return F.back();
}

Related

How to compute first N digits of Euler number in c++? [duplicate]

Can anyone explain how this code for computing of e works? Looks very easy for such complicated task, but I can't even understand the process. It has been created by Xavier Gourdon in 1999.
int main() {
int N = 9009, a[9009], x = 0;
for (int n = N - 1; n > 0; --n) {
a[n] = 1;
}
a[1] = 2, a[0] = 0;
while (N > 9) {
int n = N--;
while (--n) {
a[n] = x % n;
x = 10 * a[n-1] + x/n;
}
printf("%d", x);
}
return 0;
}
I traced the algorithm back to a 1995 paper by Stanley Rabinowitz and Stan Wagon. It's quite interesting.
A bit of background first. Start with the ordinary decimal representation of e:
e = 2.718281828...
This can be expressed as an infinite sum as follows:
e = 2 + 1⁄10(7 + 1⁄10(1 + 1⁄10(8 + 1⁄10(2 + 1⁄10(8 + 1⁄10(1 ...
Obviously this isn't a particularly useful representation; we just have the same digits of e wrapped up inside a complicated expression.
But look what happens when we replace these 1⁄10 factors with the reciprocals of the natural numbers:
e = 2 + 1⁄2(1 + 1⁄3(1 + 1⁄4(1 + 1⁄5(1 + 1⁄6(1 + 1⁄7(1 ...
This so-called mixed-radix representation gives us a sequence consisting of the digit 2 followed by a repeating sequence of 1's. It's easy to see why this works. When we expand the brackets, we end up with the well-known Taylor series for e:
e = 1 + 1 + 1/2! + 1/3! + 1/4! + 1/5! + 1/6! + 1/7! + ...
So how does this algorithm work? Well, we start by filling an array with the mixed-radix number (0; 2; 1; 1; 1; 1; 1; ...). To generate each successive digit, we simply multiply this number by 10 and spit out the leftmost digit.*
But since the number is represented in mixed-radix form, we have to work in a different base at each digit. To do this, we work from right to left, multiplying the nth digit by 10 and replacing it with the resulting value modulo n. If the result was greater than or equal to n, we carry the value x/n to the next digit to the left. (Dividing by n changes the base from 1/n! to 1/(n-1)!, which is what we want). This is effectively what the inner loop does:
while (--n) {
a[n] = x % n;
x = 10 * a[n-1] + x/n;
}
Here, x is initialized to zero at the start of the program, and the initial 0 at the start of the array ensures that it is reset to zero every time the inner loop finishes. As a result, the array will gradually fill with zeroes from the right as the program runs. This is why n can be initialized with the decreasing value N-- at each step of the outer loop.
The additional 9 digits at the end of the array are presumably included to safeguard against rounding errors. When this code is run, x reaches a maximum value of 89671, which means the quotients will be carried across multiple digits.
Notes:
This is a type of spigot algorithm, because it outputs successive digits of e using simple integer arithmetic.
As noted by Rabinowitz and Wagon in their paper, this algorithm was actually invented 50 years ago by A.H.J. Sale
* Except at the first iteration where it outputs two digits ("27")

Divide array into smaller consecutive parts such that NEO value is maximal

On this years Bubble Cup (finished) there was the problem NEO (which I couldn't solve), which asks
Given array with n integer elements. We divide it into several part (may be 1), each part is a consecutive of elements. The NEO value in that case is computed by: Sum of value of each part. Value of a part is sum all elements in this part multiple by its length.
Example: We have array: [ 2 3 -2 1 ]. If we divide it like: [2 3] [-2 1]. Then NEO = (2 + 3) * 2 + (-2 + 1) * 2 = 10 - 2 = 8.
The number of elements in array is smaller then 10^5 and the numbers are integers between -10^6 and 10^6
I've tried something like divide and conquer to constantly split array into two parts if it increases the maximal NEO number otherwise return the NEO of the whole array. But unfortunately the algorithm has worst case O(N^2) complexity (my implementation is below) so I'm wondering whether there is a better solution
EDIT: My algorithm (greedy) doesn't work, taking for example [1,2,-6,2,1] my algorithm returns the whole array while to get the maximal NEO value is to take parts [1,2],[-6],[2,1] which gives NEO value of (1+2)*2+(-6)+(1+2)*2=6
#include <iostream>
int maxInterval(long long int suma[],int first,int N)
{
long long int max = -1000000000000000000LL;
long long int curr;
if(first==N) return 0;
int k;
for(int i=first;i<N;i++)
{
if(first>0) curr = (suma[i]-suma[first-1])*(i-first+1)+(suma[N-1]-suma[i])*(N-1-i); // Split the array into elements from [first..i] and [i+1..N-1] store the corresponding NEO value
else curr = suma[i]*(i-first+1)+(suma[N-1]-suma[i])*(N-1-i); // Same excpet that here first = 0 so suma[first-1] doesn't exist
if(curr > max) max = curr,k=i; // find the maximal NEO value for splitting into two parts
}
if(k==N-1) return max; // If the max when we take the whole array then return the NEO value of the whole array
else
{
return maxInterval(suma,first,k+1)+maxInterval(suma,k+1,N); // Split the 2 parts further if needed and return it's sum
}
}
int main() {
int T;
std::cin >> T;
for(int j=0;j<T;j++) // Iterate over all the test cases
{
int N;
long long int NEO[100010]; // Values, could be long int but just to be safe
long long int suma[100010]; // sum[i] = sum of NEO values from NEO[0] to NEO[i]
long long int sum=0;
int k;
std::cin >> N;
for(int i=0;i<N;i++)
{
std::cin >> NEO[i];
sum+=NEO[i];
suma[i] = sum;
}
std::cout << maxInterval(suma,0,N) << std::endl;
}
return 0;
}
This is not a complete solution but should provide some helpful direction.
Combining two groups that each have a positive sum (or one of the sums is non-negative) would always yield a bigger NEO than leaving them separate:
m * a + n * b < (m + n) * (a + b) where a, b > 0 (or a > 0, b >= 0); m and n are subarray lengths
Combining a group with a negative sum with an entire group of non-negative numbers always yields a greater NEO than combining it with only part of the non-negative group. But excluding the group with the negative sum could yield an even greater NEO:
[1, 1, 1, 1] [-2] => m * a + 1 * (-b)
Now, imagine we gradually move the dividing line to the left, increasing the sum b is combined with. While the expression on the right is negative, the NEO for the left group keeps decreasing. But if the expression on the right gets positive, relying on our first assertion (see 1.), combining the two groups would always be greater than not.
Combining negative numbers alone in sequence will always yield a smaller NEO than leaving them separate:
-a - b - c ... = -1 * (a + b + c ...)
l * (-a - b - c ...) = -l * (a + b + c ...)
-l * (a + b + c ...) < -1 * (a + b + c ...) where l > 1; a, b, c ... > 0
O(n^2) time, O(n) space JavaScript code:
function f(A){
A.unshift(0);
let negatives = [];
let prefixes = new Array(A.length).fill(0);
let m = new Array(A.length).fill(0);
for (let i=1; i<A.length; i++){
if (A[i] < 0)
negatives.push(i);
prefixes[i] = A[i] + prefixes[i - 1];
m[i] = i * (A[i] + prefixes[i - 1]);
for (let j=negatives.length-1; j>=0; j--){
let negative = prefixes[negatives[j]] - prefixes[negatives[j] - 1];
let prefix = (i - negatives[j]) * (prefixes[i] - prefixes[negatives[j]]);
m[i] = Math.max(m[i], prefix + negative + m[negatives[j] - 1]);
}
}
return m[m.length - 1];
}
console.log(f([1, 2, -5, 2, 1, 3, -4, 1, 2]));
console.log(f([1, 2, -4, 1]));
console.log(f([2, 3, -2, 1]));
console.log(f([-2, -3, -2, -1]));
Update
This blog provides that we can transform the dp queries from
dp_i = sum_i*i + max(for j < i) of ((dp_j + sum_j*j) + (-j*sum_i) + (-i*sumj))
to
dp_i = sum_i*i + max(for j < i) of (dp_j + sum_j*j, -j, -sum_j) ⋅ (1, sum_i, i)
which means we could then look at each iteration for an already seen vector that would generate the largest dot product with our current information. The math alluded to involves convex hull and farthest point query, which are beyond my reach to implement at this point but will make a study of.

How to reduce execution time in C++ for the following code?

I have written this code which has an execution time of 3.664 sec but the time limit is 3 seconds.
The question is this-
N teams participate in a league cricket tournament on Mars, where each
pair of distinct teams plays each other exactly once. Thus, there are a total
of (N × (N­1))/2 matches. An expert has assigned a strength to each team,
a positive integer. Strangely, the Martian crowds love one­sided matches
and the advertising revenue earned from a match is the absolute value of
the difference between the strengths of the two matches. Given the
strengths of the N teams, find the total advertising revenue earned from all
the matches.
Input format
Line 1 : A single integer, N.
Line 2 : N space ­separated integers, the strengths of the N teams.
#include<iostream>
using namespace std;
int main()
{
int n;
cin>>n;
int stren[200000];
for(int a=0;a<n;a++)
cin>>stren[a];
long long rev=0;
for(int b=0;b<n;b++)
{
int pos=b;
for(int c=pos;c<n;c++)
{
if(stren[pos]>stren[c])
rev+=(long long)(stren[pos]-stren[c]);
else
rev+=(long long)(stren[c]-stren[pos]);
}
}
cout<<rev;
}
Can you please give me a solution??
Rewrite your loop as:
sort(stren);
for(int b=0;b<n;b++)
{
rev += (2 * b - n + 1) * static_cast<long long>(stren[b]);
}
Live code here
Why does it workYour loops make all pairs of 2 numbers and add the difference to rev. So in a sorted array, bth item is subtracted (n-1-b) times and added b times. Hence the number 2 * b - n + 1
There can be 1 micro optimization that possibly is not needed:
sort(stren);
for(int b = 0, m = 1 - n; b < n; b++, m += 2)
{
rev += m * static_cast<long long>(stren[b]);
}
In place of the if statement, use
rev += std::abs(stren[pos]-stren[c]);
abs returns the positive difference between two integers. This will be much quicker than an if test and ensuing branching. The (long long) cast is also unnecessary although the compiler will probably optimise that out.
There are other optimisations you could make, but this one should do it. If your abs function is poorly implemented on your system, you could always make use of this fast version for computing the absolute value of i:
(i + (i >> 31)) ^ (i >> 31) for a 32 bit int.
This has no branching at all and would beat even an inline ternary! (But you should use int32_t as your data type; if you have 64 bit int then you'll need to adjust my formula.) But we are in the realms of micro-optimisation here.
for(int b = 0; b < n; b++)
{
for(int c = b; c < n; c++)
{
rev += abs(stren[b]-stren[c]);
}
}
This should give you a speed increase, might be enough.
An interesting approach might be to collapse down the strengths from an array - if that distribution is pretty small.
So:
std::unordered_map<int, int> strengths;
for (int i = 0; i < n; ++i) {
int next;
cin >> next;
++strengths[next];
}
This way, we can reduce the number of things we have to sum:
long long rev = 0;
for (auto a = strengths.begin(); a != strengths.end(); ++a) {
for (auto b = std::next(a), b != strengths.end(); ++b) {
rev += abs(a->first - b->first) * (a->second * b->second);
// ^^^^ stren diff ^^^^^^^^ ^^ number of occurences ^^
}
}
cout << rev;
If the strengths tend to be repeated a lot, this could save a lot of cycles.
What exactly we are doing in this problem is: For all combinations of pairs of elements, we are adding up the absolute values of the differences between the elements of the pair. i.e. Consider the sample input
3 10 3 5
Ans (Take only absolute values) = (3-10) + (3-3) + (3-5) + (10-3) + (10-5) + (3-5) = 7 + 0 + 2 + 7 + 5 + 2 = 23
Notice that I have fixed 3, iterated through the remaining elements, found the differences and added them to Ans, then fixed 10, iterated through the remaining elements and so on till the last element
Unfortunately, N(N-1)/2 iterations are required for the above procedure, which wouldn't be ok for the time limit.
Could we better it?
Let's sort the array and repeat this procedure. After sorting, the sample input is now 3 3 5 10
Let's start by fixing the greatest element, 10 and iterating through the array like how we did before (of course, the time complexity is the same)
Ans = (10-3) + (10-3) + (10-5) + (5-3) + (5-3) + (3-3) = 7 + 7 + 5 + 2 + 2 = 23
We could rearrange the above as
Ans = (10)(3)-(3+3+5) + 5(2) - (3+3) + 3(1) - (3)
Notice a pattern? Let's generalize it.
Suppose we have an array of strengths arr[N] of size N indexed from 0
Ans = (arr[N-1])(N-1) - (arr[0] + arr[1] + ... + arr[N-2]) + (arr[N-2])(N-2) - (arr[0] + arr[1] + arr[N-3]) + (arr[N-3])(N-3) - (arr[0] + arr[1] + arr[N-4]) + ... and so on
Right. So let's put this new idea to work. We'll introduce a 'sum' variable. Some basic DP to the rescue.
For i=0 to N-1
sum = sum + arr[i]
Ans = Ans + (arr[i+1]*(i+1)-sum)
That's it, you just have to sort the array and iterate only once through it. Excluding the sorting part, it's down to N iterations from N(N-1)/2, I suppose that's called O(N) time EDIT: That is O(N log N) time overall
Hope it helped!

Indices of objects in a list of non-redundant pairs

I am implementing a collision detection algorithm stores the distance between all the objects in a single octree node. For instance if there are 4 objects in the node, there is a distance between objects 1&2, 1&3, 1&4, 2&3, 2&4 and 3&4. The formula for the total number of pairs is t = n * (n-1) / 2, where t is the total number of pairs and n is the number of objects in a node.
My question is, how do I convert from a position in the list to a pair of objects. For instance, using the above list of pairs, 3 would return the pair 2&3.
To save space in memory, the list is just a list of floats for the distance instead of containing distance and pointers to 2 objects.
I am unsure how to mathematically convert the single list index to a pair of numbers. Any help would be great. I am hoping to be able to break this down to 2 functions, the first returns the first object in the pair and the second returns the second, both the functions taking 2 variables, one being the index and the other being the total objects in the node. If possible I would like to make a function without any looping or having a recursive function because this will be run in real time for my collision detection algorithm.
Better ordering
I suggest using colexicographical order, as in that case you won't have to supply the total number of objects. Order your pairs like this:
0: 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: …
0&1, 0&2, 1&2, 0&3, 1&3, 2&3, 0&4, 1&4, 2&4, 3&4, 0&5, 1&5, 2&5, 3&5, …
You'll ve able to extend this list to infinite length, so you can know the index of any pair without knowing the number of items. This has the benefit that when you add new items to your data structure, you'll only have to append to your arrays, not relocate existing entries. I've adjusted the indices to zero-based, as you tagged your question C++ so I assume you'll be using zero-based indexing. All my answer below assumes this ordering.
You can also visualize the colex ordering like this:
a: 0 1 2 3 4 5 …
b:
1 0
2 1 2 index of
3 3 4 5 a&b
4 6 7 8 9
5 10 11 12 13 14
6 15 16 17 18 19 20
⋮ ⋮ ⋱
Pair to single index
Let us first turn a pair into a single index. The trick is that for every pair, you look at the second position and imagine all the pairs that had a lesser number in that position. So for example for the pair 2&4 you first count all the pairs where the second number is less than 4. This is the number of possible ways to choose two items from a set of 4 (i.e. the numbers 0 through 3), so you could express this as a binomial coefficient 4C2. If you evaluate it, you end up with 4(4−1)/2=6. To that you add the first number, as this is the number of pairs with lower index but with the same number in the second place. For 2&4 this is 2, so the overall index of 2&4 is 4(4−1)/2+2=8.
In general, for a pair a&b the index will be b(b−1)/2+a.
int index_from_pair(int a, int b) {
return b*(b - 1)/2 + a;
}
Single index to pair
One way to turn the single index i back into a pair of numbers would be increasing b until b(b+1)/2 > i, i.e. the situation where the next value of b would result in indices larger than i. Then you can find a as the difference a = i−b(b−1)/2. This approach by incrementing b one at a time involves using a loop.
pair<int, int> pair_from_index(int i) {
int a, b;
for (b = 0; b*(b + 1)/2 <= i; ++b)
/* empty loop body */;
a = i - b*(b - 1)/2;
return make_pair(a, b);
}
You could also interpret b(b−1)/2 = i as a quadratic equation, which you can solve using a square root. The real b you need is the floor of the floating point b you'd get as the positive solution to this quadratic equation. As you might encounter problems due to rounding errors in this approach, you might want to check whether b(b+1)/2 > i. If that is not the case, increment b as you would do in the loop approach. Once you have b, the computation of a remains the same.
pair<int, int> pair_from_index(int i) {
int b = (int)floor((sqrt(8*i + 1) + 1)*0.5);
if (b*(b + 1)/2 <= i) ++b; // handle possible rounding error
int a = i - b*(b - 1)/2;
return make_pair(a, b);
}
Sequential access
Note that you only need to turn indices back to pairs for random access to your list. When iterating over all pairs, a set of nested loops is easier. So instead of
for (int = 0; i < n*(n - 1)/2; ++i) {
pair<int, int> ab = pair_from_index(i);
int a = ab.first, b = ab.second;
// do stuff
}
you'd better write
for (int i = 0, b = 1; b != n; ++b) {
for (int a = 0; a != b; ++a) {
// do stuff
++i;
}
}
Based on my understanding of the question, one way to get a pair a&b (1-based, 2&3 in your example) from the index (0-based, 3 in your example) and the number of objects n (4 in your example) is:
t = n * (n - 1) / 2;
a = n - floor((1 + sqrt(1 + 8 * (t - index - 1))) / 2);
b = index + (n - a) * (n - a + 1) / 2 - t + a + 1;
Some credits to http://oeis.org/A002024
Generalized algorithms (for tuples rather than pairs) can be found at Calculate Combination based on position and http://saliu.com/bbs/messages/348.html, but they seem to involve calculating combinations in a loop.
Edit: a nicer formula for a (from the same source):
a = n - floor(0.5 + sqrt(2 * (t - index)));

Finding all paths down stairs?

I was given the following problem in an interview:
Given a staircase with N steps, you can go up with 1 or 2 steps each time. Output all possible way you go from bottom to top.
For example:
N = 3
Output :
1 1 1
1 2
2 1
When interviewing, I just said to use dynamic programming.
S(n) = S(n-1) +1 or S(n) = S(n-1) +2
However, during the interview, I didn't write very good code for this. How would you code up a solution to this problem?
Thanks indeed!
I won't write the code for you (since it's a great exercise), but this is a classic dynamic programming problem. You're on the right track with the recurrence; it's true that
S(0) = 1
Since if you're at the bottom of the stairs there's exactly one way to do this. We also have that
S(1) = 1
Because if you're one step high, your only option is to take a single step down, at which point you're at the bottom.
From there, the recurrence for the number of solutions is easy to find. If you think about it, any sequence of steps you take either ends with taking one small step as your last step or one large step as your last step. In the first case, each of the S(n - 1) solutions for n - 1 stairs can be extended into a solution by taking one more step, while in the second case each of the S(n - 2) solutions to the n - 2 stairs case can be extended into a solution by taking two steps. This gives the recurrence
S(n) = S(n - 2) + S(n - 1)
Notice that to evaluate S(n), you only need access to S(n - 2) and S(n - 1). This means that you could solve this with dynamic programming using the following logic:
Create an array S with n + 1 elements in it, indexed by 0, 1, 2, ..., n.
Set S[0] = S[1] = 1
For i from 2 to n, inclusive, set S[i] = S[i - 1] + S[i - 2].
Return S[n].
The runtime for this algorithm is a beautiful O(n) with O(n) memory usage.
However, it's possible to do much better than this. In particular, let's take a look at the first few terms of the sequence, which are
S(0) = 1
S(1) = 1
S(2) = 2
S(3) = 3
S(4) = 5
This looks a lot like the Fibonacci sequence, and in fact you might be able to see that
S(0) = F(1)
S(1) = F(2)
S(2) = F(3)
S(3) = F(4)
S(4) = F(5)
This suggests that, in general, S(n) = F(n + 1). We can actually prove this by induction on n as follows.
As our base cases, we have that
S(0) = 1 = F(1) = F(0 + 1)
and
S(1) = 1 = F(2) = F(1 + 1)
For the inductive step, we get that
S(n) = S(n - 2) + S(n - 1) = F(n - 1) + F(n) = F(n + 1)
And voila! We've gotten this series written in terms of Fibonacci numbers. This is great, because it's possible to compute the Fibonacci numbers in O(1) space and O(lg n) time. There are many ways to do this. One uses the fact that
F(n) = (1 / √(5)) (Φn + φn)
Here, Φ is the golden ratio, (1 + √5) / 2 (about 1.6), and φ is 1 - Φ, about -0.6. Because this second term drops to zero very quickly, you can get a the nth Fibonacci number by computing
(1 / √(5)) Φn
And rounding down. Moreover, you can compute Φn in O(lg n) time by repeated squaring. The idea is that we can use this cool recurrence:
x0 = 1
x2n = xn * xn
x2n + 1 = x * xn * xn
You can show using a quick inductive argument that this terminates in O(lg n) time, which means that you can solve this problem using O(1) space and O(lg n) time, which is substantially better than the DP solution.
Hope this helps!
You can generalize your recursive function to also take already made moves.
void steps(n, alreadyTakenSteps) {
if (n == 0) {
print already taken steps
}
if (n >= 1) {
steps(n - 1, alreadyTakenSteps.append(1));
}
if (n >= 2) {
steps(n - 2, alreadyTakenSteps.append(2));
}
}
It's not really the code, more of a pseudocode, but it should give you an idea.
Your solution sounds right.
S(n):
If n = 1 return {1}
If n = 2 return {2, (1,1)}
Return S(n-1)x{1} U S(n-2)x{2}
(U is Union, x is Cartesian Product)
Memoizing this is trivial, and would make it O(Fib(n)).
Great answer by #templatetypedef - I did this problem as an exercise and arrived at the Fibonacci numbers on a different route:
The problem can basically be reduced to an application of Binomial coefficients which are handy for Combination problems: The number of combinations of n things taken k at a time (called n choose k) can be found by the equation
Given that and the problem at hand you can calculate a solution brute force (just doing the combination count). The number of "take 2 steps" must be zero at least and may be 50 at most, so the number of combinations is the sum of C(n,k) for 0 <= k <= 50 ( n= number of decisions to be made, k = number of 2's taken out of those n)
BigInteger combinationCount = 0;
for (int k = 0; k <= 50; k++)
{
int n = 100 - k;
BigInteger result = Fact(n) / (Fact(k) * Fact(n - k));
combinationCount += result;
}
The sum of these binomial coefficients just happens to also have a different formula:
Actually, you can prove that the number of ways to climb is just the fibonacci sequence. Good explanation here: http://theory.cs.uvic.ca/amof/e_fiboI.htm
Solving the problem, and solving it using a dynamic programming solution are potentially two different things.
http://en.wikipedia.org/wiki/Dynamic_programming
In general, to solve a given problem, we need to solve different parts of the problem (subproblems), then combine the solutions of the subproblems to reach an overall solution. Often, many of these subproblems are really the same. The dynamic programming approach seeks to solve each subproblem only once, thus reducing the number of computations
This leads me to believe you want to look for a solution that is both Recursive, and uses the Memo Design Pattern. Recursion solves a problem by breaking it into sub-problems, and the Memo design pattern allows you to cache answers, thus avoiding re-calculation. (Note that there are probably cache implementations that aren't the Memo design pattern, and you could use one of those as well).
Solving:
The first step I would take would be to solve some set of problems by hand, with varying or increasing sizes of N. This will give you a pattern to help you figure out a solution. Start with N = 1, through N = 5. (as others have stated, it may be a form of the fibbonacci sequence, but I would determine this for myself before calling the problem solved and understood).
From there, I would try to make a generalized solution that used recursion. Recursion solves a problem by breaking it into sub-problems.
From there, I would try to make a cache of previous problem inputs to the corresponding output, hence memoizing it, and making a solution that involved "Dynamic Programming".
I.e., maybe the inputs to one of your functions are 2, 5, and the correct result was 7. Make some function that looks this up from an existing list or dictionary (based on the input). It will look for a call that was made with the inputs 2, 5. If it doesn't find it, call the function to calculate it, then store it and return the answer (7). If it does find it, don't bother calculating it, and return the previously calculated answer.
Here is a simple solution to this question in very simple CSharp (I believe you can port this with almost no change to Java/C++).
I have added a little bit more of complexity to it (adding the possibility that you can also walk 3 steps). You can even generalize this code to "from 1 to k-steps" if desired with a while loop in the addition of steps (last if statement).
I have used a combination of both dynamic programming and recursion. The use of dynamic programming avoid the recalculation of each previous step; reducing the space and time complexity related to the call stack. It however adds some space complexity (O(maxSteps)) which I think is negligible compare to the gain.
/// <summary>
/// Given a staircase with N steps, you can go up with 1 or 2 or 3 steps each time.
/// Output all possible way you go from bottom to top
/// </summary>
public class NStepsHop
{
const int maxSteps = 500; // this is arbitrary
static long[] HistorySumSteps = new long[maxSteps];
public static long CountWays(int n)
{
if (n >= 0 && HistorySumSteps[n] != 0)
{
return HistorySumSteps[n];
}
long currentSteps = 0;
if (n < 0)
{
return 0;
}
else if (n == 0)
{
currentSteps = 1;
}
else
{
currentSteps = CountWays(n - 1) +
CountWays(n - 2) +
CountWays(n - 3);
}
HistorySumSteps[n] = currentSteps;
return currentSteps;
}
}
You can call it in the following manner
long result;
result = NStepsHop.CountWays(0); // result = 1
result = NStepsHop.CountWays(1); // result = 1
result = NStepsHop.CountWays(5); // result = 13
result = NStepsHop.CountWays(10); // result = 274
result = NStepsHop.CountWays(25); // result = 2555757
You can argue that the initial case when n = 0, it could 0, instead of 1. I decided to go for 1, however modifying this assumption is trivial.
the problem can be solved quite nicely using recursion:
void printSteps(int n)
{
char* output = new char[n+1];
generatePath(n, output, 0);
printf("\n");
}
void generatePath(int n, char* out, int recLvl)
{
if (n==0)
{
out[recLvl] = '\0';
printf("%s\n",out);
}
if(n>=1)
{
out[recLvl] = '1';
generatePath(n-1,out,recLvl+1);
}
if(n>=2)
{
out[recLvl] = '2';
generatePath(n-2,out,recLvl+1);
}
}
and in main:
void main()
{
printSteps(0);
printSteps(3);
printSteps(4);
return 0;
}
It's a weighted graph problem.
From 0 you can get to 1 only 1 way (0-1).
You can get to 2 two ways, from 0 and from 1 (0-2, 1-1).
You can get to 3 three ways, from 1 and from 2 (2 has two ways).
You can get to 4 five ways, from 2 and from 3 (2 has two ways and 3 has three ways).
You can get to 5 eight ways, ...
A recursive function should be able to handle this, working backwards from N.
Complete C-Sharp code for this
void PrintAllWays(int n, string str)
{
string str1 = str;
StringBuilder sb = new StringBuilder(str1);
if (n == 0)
{
Console.WriteLine(str1);
return;
}
if (n >= 1)
{
sb = new StringBuilder(str1);
PrintAllWays(n - 1, sb.Append("1").ToString());
}
if (n >= 2)
{
sb = new StringBuilder(str1);
PrintAllWays(n - 2, sb.Append("2").ToString());
}
}
Late C-based answer
#include <stdio.h>
#include <stdlib.h>
#define steps 60
static long long unsigned int MAP[steps + 1] = {1 , 1 , 2 , 0,};
static long long unsigned int countPossibilities(unsigned int n) {
if (!MAP[n]) {
MAP[n] = countPossibilities(n-1) + countPossibilities(n-2);
}
return MAP[n];
}
int main() {
printf("%llu",countPossibilities(steps));
}
Here is a C++ solution. This prints all possible paths for a given number of stairs.
// Utility function to print a Vector of Vectors
void printVecOfVec(vector< vector<unsigned int> > vecOfVec)
{
for (unsigned int i = 0; i < vecOfVec.size(); i++)
{
for (unsigned int j = 0; j < vecOfVec[i].size(); j++)
{
cout << vecOfVec[i][j] << " ";
}
cout << endl;
}
cout << endl;
}
// Given a source vector and a number, it appends the number to each source vectors
// and puts the final values in the destination vector
void appendElementToVector(vector< vector <unsigned int> > src,
unsigned int num,
vector< vector <unsigned int> > &dest)
{
for (int i = 0; i < src.size(); i++)
{
src[i].push_back(num);
dest.push_back(src[i]);
}
}
// Ladder Problem
void ladderDynamic(int number)
{
vector< vector<unsigned int> > vecNminusTwo = {{}};
vector< vector<unsigned int> > vecNminusOne = {{1}};
vector< vector<unsigned int> > vecResult;
for (int i = 2; i <= number; i++)
{
// Empty the result vector to hold fresh set
vecResult.clear();
// Append '2' to all N-2 ladder positions
appendElementToVector(vecNminusTwo, 2, vecResult);
// Append '1' to all N-1 ladder positions
appendElementToVector(vecNminusOne, 1, vecResult);
vecNminusTwo = vecNminusOne;
vecNminusOne = vecResult;
}
printVecOfVec(vecResult);
}
int main()
{
ladderDynamic(6);
return 0;
}
may be I am wrong.. but it should be :
S(1) =0
S(2) =1
Here We are considering permutations so in that way
S(3) =3
S(4) =7