I am solving the following question:
You are climbing a stair case. It takes n steps to reach to the top.
Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?
by constructing the following code snippet:
class Solution {
public:
int climbStairs(int n) {
if(n==0)
return 0;
vector<int> dp(n+1);
dp[0]=0;
dp[1]=1;
for(int i=2; i<=n; i++)
dp[i] = dp[i-1] + dp[i-2];
return dp[n];
}
};
When I looked at the solutions, I found out that they make this initialization:
dp[0]=0;
dp[1]=1;
dp[2]=2; //--> Why? And when to do this?
Because of the way I initialized it, I get lower values (like the answer for n is at dp[n-1] and so on). All this, just because I didn't initialize dp[2]=2. Could someone please point out the intuition behind this particular initialization?
Thanks!
Note: Question is taken from LeetCode.com.
The code that’s posted here is incorrect, which is why you don’t see dp[2] = 2.
I believe that the DP table here is such that dp[k] represents the number of ways to climb from step n - k to step n using the rules described here. As a result, dp[0] should be 1, not 0. There’s one way to get from step n to step n by following these rules: namely, don’t take any steps!
Once you’ve initialized that value properly, then you’d have dp[2] = dp[0] + dp[1] = 1 + 1 = 2. There’s no need to explicitly initialize dp[2] since the value follows from the general case.
Related
What would be the time complexity of the following loop?
for (int i = 2; i < n; i = i * i) {
++a;
}
While practicing runtime complexities, I came across this code and can't find the answer. I thought this would be sqrt(n), though it doesn't seem correct, since the loop has the sequence of 2, 4, 16, 256, ....
To understand the answer you must understand that: Inverse of Exponent is not SQRT, but log is.
This loop is multiplying i by itself(.i.e. exponential increment) and will stop only when i >= n, therefore the complexity would be O(log(n)) (log to the base 2 to be precise because i=2 at initialization)
To illustrate this:
In the above image, you can see that SQRT is giving correct number of steps only when i is a even power of 2. However log2 is giving accurate number of steps everytime.
Each time i is powered by 2. Hence, if A(n) shows the current value of i in the last step (which is n), it can be written in a recursive for like the following (suppose n is power of 2):
A(n) = A(n-1)^2
Now, you can expand it to find a pattern:
A(n) = A(n-2)^4 = A(n-3)^8 = ... = A(n-(n-1))^(2^(n-1)) = 2^(2^(n-1))
Hence, the loop iterates k step such that n = 2 ^ (2^ (k-1)). Therefore, this loop iterates Theta(log(log(n)).
Link to The Problem: https://codeforces.com/problemset/problem/166/E
Problem Statement:
*You are given a tetrahedron. Let's mark its vertices with letters A, B, C, and D correspondingly.
An ant is standing in the vertex D of the tetrahedron. The ant is quite active and he wouldn't stay idle. At each moment of time, he makes a step from one vertex to another one along some edge of the tetrahedron. The ant just can't stand on one place.
You do not have to do much to solve the problem: your task is to count the number of ways in which the ant can go from the initial vertex D to itself in exactly n steps. In other words, you are asked to find out the number of different cyclic paths with the length of n from vertex D to itself. As the number can be quite large, you should print it modulo 1000000007 (10^9 + 7).*
Input:
The first line contains the only integer n (1 ≤ n ≤ 107) — the required length of the cyclic path.
Output:
Print the only integer — the required number of ways modulo 1000000007 (10e9 + 7).
Example: Input n=2 , Output: 3
Input n=4, Output: 21
My Approach to Problem:
I have written a recursive code that takes two input n and present index, then I am traveling and exploring all possible combinations.
#include<iostream>
using namespace std;
#define mod 10000000
#define ll long long
ll count_moves=0;
ll count(ll n, int present)
{
if(n==0 and present==0) count_moves+=1, count_moves%=mod; //base_condition
else if(n>1){ //Generating All possible Combinations
count(n-1,(present+1)%4);
count(n-1,(present+2)%4);
count(n-1,(present+3)%4);
}
else if(n==1 and present) count(n-1,0);
}
int main()
{
ll n; cin>>n;
if(n==1) {
cout<<"0"; return;
}
count(n,0);
cout<<count_moves%mod;
}
But the problem is that I am getting Time Limit Error since Time Complexity of my Code is very high. Please Can anyone suggest me how can I optimize/Memoize my code to reduce its complexity?
#**Edit 1: ** Some People are commenting about macros and division well it's not an issue. The Range of n is 10^7 and complexity of my code is exponential so my actual doubt is how to decrease it to linear time. i,e O(n).
Anytime you built into a recursion and you exceeded time complexity, you have to understand the recursion is likely the problem.
The best solution is to not use a recursion.
Look at the result you have:
3
6
21
60
183
546
1641
4920
⋮ ⋮
While it might be hard to find a pattern for the first couple terms, but it gets easier later on.
Each term is roughly 3 times larger than the last term, or more precisely,
Now you could just write a for loop for it:
for(int i = 0; i < n-1; i++)
{
count_moves = count_moves * 3 + std::pow(-1, i) * 3;
}
or to get rid of pow():
for(int i = 0; i < n-1; i++)
{
count_moves = count_moves * 3 + (i % 2 * 2 - 1) * -3;
}
Further more, you could even build that into a general term formula to get rid of the for loop:
or in code:
count_moves = (pow(3, n) + (n % 2 * 2 - 1) * -3) / 4;
However, you can't get rid of the pow() this time, or you will have to write a loop for that then.
I believe one of your issues is that you are recalculating things.
Take for example n=4. count(3,x) is called 3 times for x in [0,3].
However if you made a std::map<int,int> you could save the value for (n,present) pairs and only calculate each value once.
This will take more space. The map will be 4*(n-1) big when you are done. That is still probably too large for 10^9?
Another thing you can do is multithread. Each call to count can instigate its own thread. You need to be careful then to be thread safe when changing the global count and the state of the std::map if you decide to use it.
Edit:
Calculate count(n,x) one time for n in [1,n-1] x in [0,3] then count[n,0] = a*count(n-1,1) +b*count(n-1,2) +c*count(n-1,3).
If you can figure out the pattern for what a,b,c are given n or maybe even the a,b,c for the n-1 case then you may be able to solve this problem easily.
I coded the following solution with some online help. The aim is basically to find the number of ways in which a person can climb a ladder of n steps, if at each step he can climb 1 or 2 steps.
class Solution {
public:
int climbStairs(int n) {
if(n<0)
return 0;
//what is the logic used for the following return?
if(n==0)
return 1;
return climbStairs(n-1)+climbStairs(n-2);
}
};
While I am more or less aware about what exactly I am doing, I fail to understand the intuition behind returning 1 if the number of steps to be climbed is 0. Since we can take strides of length either 1 or 2, if the total number of steps to be climbed is 0, then shouldn't we return just a 0 (since no steps of length 1 or 2 can be taken)? Unfortunately, I don't get the correct answer if I return 0.
Could someone please explain what exactly is going on and the intuition behind returning 1 (instead of a 0)?
Instead of thinking about it in terms of how many different ways you can take steps to the top, think of it in terms of how many ways you can get to the top when you have n steps left to climb. If n == 0 you have one way to get to the top: stay where you are. That's the intuition.
The practical reason is that without that definition for n == 0, you'd need two more base cases, for n == 1 and n == 2 to get the right answer for all n > 0. And then you would be free to puzzle over what the right answer should be for n == 0.
Per request, here's why you'd need additional base cases if climbStairs(0) was 0. (Well, either you need additional base cases or you need to alter your recursion formula.) Whenever n is not a base case, climbStairs(n) is defined in terms of climbStairs(n-1) and climbStairs(n-2). If you define the n == 0 case as being 0, then, as you noticed, you don't get the right answer for n == 1 or n == 2. Therefore you'd have to define those as additional base cases. (Just fixing the n == 1 still wouldn't give the right answer for n == 2.) Once those additional base cases are established, the recursion formula will continue to give the correct answer for all n > 2.
There's one way to climb no stairs: do nothing. Or you can think of it mathematically: an empty sum is 0.
If you feel uncomfortable with that intuition, you can rephrase your code to eliminate the zero case:
int climbStairs(int n) {
if (n == 1) return 1; // 1
if (n == 2) return 2; // 1+1 or 2
return climbStairs(n-1) + climbStairs(n-2);
}
Incidental to your actual question, but this function is the Fibonacci sequence, and there are better ways (eg: linear or log time rather than exponential) to compute it.
When a person climbs the stairs, Let's say he goes from point A to point B by climbing n stairs. Now as one can easily understand there's some an vertical distance and bn horizontal distance between A and B. Where a and b are dimensions of each stair.
'Could someone please explain what exactly is going on and the intuition behind returning 1 (instead of a 0)?'
Now when there is 0 stairs there is no vertical distance between A and B. But there is 'b' horizontal distance that has to be covered and which will require 1 step.
If we returned 0 when n == 0 and when n < 0, then both our base cases would return 0 and we would always get 0 as our final answer, since return climbStairs(n-1)+climbStairs(n-2); would always perform 0+0. Don't worry about how a ladder with zero steps can even be "climbed" at all - it just has to do with making the program give the correct answer for higher cases.
I need to XOR each possible pair of elements in an array, and then OR those results together.
Is it possible to do this in O(N)?
Example:-
If list contain three numbers 10,15 & 17, Then there will be a total of 3 pairs:
d1=10^15=5;
d2=10^17=27;
d3=17^15=30;
k= d1 | d2 | d3 ;
K=31
Acutually, it's even easier than Tanmay suggests.
It turns out that most of the pairs are redundant: (A^B)|(A^C)|(B^C) == (A^B)|(A^C) and
(A^B)|(A^C)|(A^D)|(B^C)|(B^D)|(C^D) == (A^B)|(A^C)|(A^D), etc. So you can just XOR each element with the first, and OR the results:
result = 0;
for (i=1; i<N;i++){
result|=data[0]^data[i];
}
OR everything, NAND everything, AND both results
Finding all combinations in O(1) is obviously impossible. So the solution had to be something ad-hoc reformulation of the problem. This is a complete intuition. (I don't have proof, but it works).
I am not sure how to solve it mathematically using boolean algebra since it involves finding all combination pairs, but I'll try to explain it using Venn diagram.
The required area is exactly identical to Venn diagram of OR except for the area of AND. Therefore they have to be subtracted. If you try it with n > 3, the picture would be even clearer.
The best way to test this method would be to simulate it with algorithms which don't have to be O(1). Anyways, you can try finding a direct proof. If you find it, please kindly share it with us too. :)
As far as your question goes, I'm sure you can implement it in O(1) yourself easily.
Good luck.
Bitwise means that you only care about 1 or 0...
The OR phase is true if at least one "pair XOR" is true.
There exists only two series for which all "pair XOR" are false : 1,1,1,1,1,1,1,1 and 0,0,0,0,0,0.
The solution is therefore a for loop to test if all items are 1 or 0.
And this is O(n) !
Bye,
You can just do what is straightforward: loop over all the pairs, 'xor' them, and 'or' the sub results. Here is a function that expects a pointer to the start of the array, and the size of the array. I typed it here without trying it, but even if it is not correct, I hope you get the idea.
unsigned int compute(const unsigned int *p, size_t size)
{
assert(size >= 2);
size_t counter = size - 1;
unsigned int value = 0;
while (counter != 0) {
value |= *p ^ *(p + 1);
++p;
--counter;
}
return value;
}
I am given a array A[] having N elements which are positive integers
.I have to find the number of sequences of lengths 1,2,3,..,N that satisfy a particular property?
I have built an interval tree with O(nlogn) complexity.Now I want to count the number of sequences that satisfy a certain property ?
All the properties required for the problem are related to sum of the sequences
Note an array will have N*(N+1)/2 sequences. How can I iterate over all of them in O(nlogn) or O(n) ?
If we let k be the moving index from 0 to N(elements), we will run an algorithm that is essentially looking for the MIN R that satisfies the condition (lets say I), then every other subset for L = k also is satisfied for R >= I (this is your short circuit). After you find I, simply return an output for (L=k, R>=I). This of course assumes that all numerics in your set are >= 0.
To find I, for every k, begin at element k + (N-k)/2. Figure out if this defined subset from (L=k, R=k+(N-k)/2) satisfies your condition. If it does, then decrement R until your condition is NOT met, then R=1 is your MIN (your could choose to print these results as you go, but they results in these cases would be essentially printed backwards). If (L=k, R=k+(N-k)/2) does not satisfy your condition, then INCREMENT R until it does, and this becomes your MIN for that L=k. This degrades your search space for each L=k by a factor of 2. As k increases and approaches N, your search space continuously decreases.
// This declaration wont work unless N is either a constant or MACRO defined above
unsigned int myVals[N];
unsigned int Ndiv2 = N / 2;
unsigned int R;
for(unsigned int k; k < N; k++){
if(TRUE == TESTVALS(myVals, k, Ndiv2)){ // It Passes
for(I = NDiv2; I>=k; I--){
if(FALSE == TESTVALS(myVals, k, I)){
I++;
break;
}
}
}else{ // It Didnt Pass
for(I = NDiv2; I>=k; I++){
if(TRUE == TESTVALS(myVals, k, I)){
break;
}
}
}
// PRINT ALL PAIRS from L=k, from R=I to R=N-1
if((k & 0x00000001) == 0) Ndiv2++;
} // END --> for(unsigned int k; k < N; k++)
The complexity of the algorithm above is O(N^2). This is because for each k in N(i.e. N iterations / tests) there is no greater than N/2 values for each that need testing. Big O notation isnt concerned about the N/2 nor the fact that truly N gets smaller as k grows, it is concerned with really only the gross magnitude. Thus it would say N tests for every N values thus O(N^2)
There is an Alternative approach which would be FASTER. That approach would be to whenever you wish to move within the secondary (inner) for loops, you could perform a move have the distance algorithm. This would get you to your O(nlogn) set of steps. For each k in N (which would all have to be tested), you run this half distance approach to find your MIN R value in logN time. As an example, lets say you have a 1000 element array. when k = 0, we essentially begin the search for MIN R at index 500. If the test passes, instead of linearly moving downward from 500 to 0, we test 250. Lets say the actual MIN R for k = 0 is 300. Then the tests to find MIN R would look as follows:
R=500
R=250
R=375
R=312
R=280
R=296
R=304
R=300
While this is oversimplified, your are most likely going to have to optimize, and test 301 as well 299 to make sure youre in the sweet spot. Another not is to be careful when dividing by 2 when you have to move in the same direction more than once in a row.
#user1907531: First of all , if you are participating in an online contest of such importance at national level , you should refrain from doing this cheap tricks and methodologies to get ahead of other deserving guys. Second, a cheater like you is always a cheater but all this hampers the hard work of those who have put in making the questions and the competitors who are unlike you. Thirdly, if #trumetlicks asks you why haven't you tagged the ques as homework , you tell another lie there.And finally, I don't know how could so many people answer this question this cheater asked without knowing the origin/website/source of this question. This surely can't be given by a teacher for homework in any Indian school. To tell everyone this cheater has asked you the complete solution of a running collegiate contest in India 6 hours before the contest ended and he has surely got a lot of direct helps and top of that invited 100's others to cheat from the answers given here. So, good luck to all these cheaters .