Count ways to n'th stair(order does not matter) - c++

There are N stairs, and a person standing at the bottom wants to reach the top. The person can climb either 1 stair or 2 stairs at a time. Count the number of ways, the person can reach the top (order does not matter).
Note: Order does not matter means for n=4 {1 2 1},{2 1 1},{1 1 2} are considered same.
https://practice.geeksforgeeks.org/problems/count-ways-to-nth-stairorder-does-not-matter/0
So I have been trying to solve this question and the problem I am facing is that I don't understand how do we solve questions like these where the order does not matter? I was able to solve the question when order mattered but I am not able to develop the logic to solve this.
This is the code I wrote for when order mattered
long int countWaysToStair(long int N)
{
if(N == 1 || N == 2)
return N;
long int dp[N+1];
dp[0] = 1;
dp[1] = 1;
dp[2] = 2;
for(int i=3;i<=N;i++)
{
dp[i] = dp[i-1] + dp[i-2];
}
return dp[N];
}
Input:
4
Expected Output:
3
My output:
5

Consider that you have N stairs. First of all you have to understand if N is odd or even.
If is even than it will be a multiple of 2: N = 2*S, where S is the number of pair of stairs.
Suppose N = 6 and S = 3. Your first solution is {2,2,2}. than you can change the first 2 stairs with 1 + 1 stairs and you have your second solution {1, 1, 2 ,2}.
Since order doesn't matter let's proceed with the next pair and we have our third solution {1, 1, 1, 1, 2} and then the fourth {1, 1, 1, 1, 1, 1}
Given N = 2*S the number of possible solutions are S + 1.
Now suppose N is odd and N = 2S + 1.
Let N = 7 and S = 3. Our solutions are {2,2,2,1}, {1,1,2,2,1}, {1,1,1,1,2,1} and {1,1,1,1,1,1,1}. Again, the number of solutions is given by S+1
Now your algorithm is pretty simple:
return N/2 + 1

The above answer is correct, but if you want to know how DP is used in this problem, look at this example:
jumps =[1,2]
Lets say that jump =1, so for any stair, the number of ways will always be equal to 1.
Now for jump=2, say for stair 8: no of ways will be (no of ways to reach 8 using 1 only)+(no of ways to reach 6 using both 1 and 2 because you can reach to 8 from 6 by just a jump of 2).
So the code will looks like:
for(int i=1; i<=n;i++)
dp[i]=1;
for(int i=2;i<=n;i++)
dp[i]=dp[i]+dp[i-2];
return dp[n];

Since the order does not matter, ways to reach at the Nth place would be:
1 way:
1,1,1,1,1....... 1
remaining n/2 ways:
1,1,1,1,1.......2
1,1,1,1,1.....2,2
.
.
.
1,2,2,2,2,2,2...2,2,2 or 2,2,2,2,2,2,2....2 (depends whether n is even or odd).
we can safely say that ways to reach at the Nth place would be n/2 +1

Related

Every sum possibilities of elements

From a given array (call it numbers[]), i want another array (results[]) which contains all sum possibilities between elements of the first array.
For example, if I have numbers[] = {1,3,5}, results[] will be {1,3,5,4,8,6,9,0}.
there are 2^n possibilities.
It doesn't matter if a number appears two times because results[] will be a set
I did it for sum of pairs or triplet, and it's very easy. But I don't understand how it works when we sum 0, 1, 2 or n numbers.
This is what I did for pairs :
std::unordered_set<int> pairPossibilities(std::vector<int> &numbers) {
std::unordered_set<int> results;
for(int i=0;i<numbers.size()-1;i++) {
for(int j=i+1;j<numbers.size();j++) {
results.insert(numbers.at(i)+numbers.at(j));
}
}
return results;
}
Also, assuming that the numbers[] is sorted, is there any possibility to sort results[] while we fill it ?
Thanks!
This can be done with Dynamic Programming (DP) in O(n*W) where W = sum{numbers}.
This is basically the same solution of Subset Sum Problem, exploiting the fact that the problem has optimal substructure.
DP[i, 0] = true
DP[-1, w] = false w != 0
DP[i, w] = DP[i-1, w] OR DP[i-1, w - numbers[i]]
Start by following the above solution to find DP[n, sum{numbers}].
As a result, you will get:
DP[n , w] = true if and only if w can be constructed from numbers
Following on from the Dynamic Programming answer, You could go with a recursive solution, and then use memoization to cache the results, top-down approach in contrast to Amit's bottom-up.
vector<int> subsetSum(vector<int>& nums)
{
vector<int> ans;
generateSubsetSum(ans,0,nums,0);
return ans;
}
void generateSubsetSum(vector<int>& ans, int sum, vector<int>& nums, int i)
{
if(i == nums.size() )
{
ans.push_back(sum);
return;
}
generateSubsetSum(ans,sum + nums[i],nums,i + 1);
generateSubsetSum(ans,sum,nums,i + 1);
}
Result is : {9 4 6 1 8 3 5 0} for the set {1,3,5}
This simply picks the first number at the first index i adds it to the sum and recurses. Once it returns, the second branch follows, sum, without the nums[i] added. To memoize this you would have a cache to store sum at i.
I would do something like this (seems easier) [I wanted to put this in comment but can't write the shifting and removing an elem at a time - you might need a linked list]
1 3 5
3 5
-----
4 8
1 3 5
5
-----
6
1 3 5
3 5
5
------
9
Add 0 to the list in the end.
Another way to solve this is create a subset arrays of vector of elements then sum up each array's vector's data.
e.g
1 3 5 = {1, 3} + {1,5} + {3,5} + {1,3,5} after removing sets of single element.
Keep in mind that it is always easier said than done. A single tiny mistake along the implemented algorithm would take a lot of time in debug to find it out. =]]
There has to be a binary chop version, as well. This one is a bit heavy-handed and relies on that set of answers you mention to filter repeated results:
Split the list into 2,
and generate the list of sums for each half
by recursion:
the minimum state is either
2 entries, with 1 result,
or 3 entries with 3 results
alternatively, take it down to 1 entry with 0 results, if you insist
Then combine the 2 halves:
All the returned entries from both halves are legitimate results
There are 4 additional result sets to add to the output result by combining:
The first half inputs vs the second half inputs
The first half outputs vs the second half inputs
The first half inputs vs the second half outputs
The first half outputs vs the second half outputs
Note that the outputs of the two halves may have some elements in common, but they should be treated separately for these combines.
The inputs can be scrubbed from the returned outputs of each recursion if the inputs are legitimate final results. If they are they can either be added back in at the top-level stage or returned by the bottom level stage and not considered again in the combining.
You could use a bitfield instead of a set to filter out the duplicates. There are reasonably efficient ways of stepping through a bitfield to find all the set bits. The max size of the bitfield is the sum of all the inputs.
There is no intelligence here, but lots of opportunity for parallel processing within the recursion and combine steps.

C++ : Inserting Operator + and - In an array and check if it is possible to create n

Problem : If you were given a number n, you will have an array with (n-1) index. with the 1st index containing 1, 2nd index containing 2, and n-1 index containing n-1. Given those sets of numbers, How can one check when + or -, the array can be equal to n?
Example :
n = 3, Array = {1,2}
+1 +2 = 3 (True)
n = 4, Array = {1,2,3}
-1 + 2 + 3 = 4 (True)
n = 5, Array = {1,2,3,4}
No possible combination
I tried too long to think about it and still haven't come up with the right answer :(
If you ale looking for simple solvable/not solvable answer, then it seems the answer if very simple
(sum - n) % 2 != 0 // => non-solvable
Here is result of an experiment:
When n gets larger it becomes easier to subtract necessary sum and there are plenty of possible solutions.

Finding the permutation that satisfy given condition

I want to find out the number of all permutation of nnumber.Number will be from 1 to n.The given condition is that each ithposition can have number up to Si,where Si is given for each position of number.
1<=n<=10^6
1<=si<=n
For example:
n=5
then its all five element will be
1,2,3,4,5
and given Si for each position is as:
2,3,4,5,5
It shows that at:
1st position can have 1 to 2that is 1,2 but can not be number among 3 to 5.
Similarly,
At 2nd position can have number 1 to 3 only.
At 3rd position can have number 1 to 4 only.
At 4th position can have number 1 to 5 only.
At 5th position can have number 1 to 5 only.
Some of its permutation are:
1,2,3,4,5
2,3,1,4,5
2,3,4,1,5 etc.
But these can not be:
3,1,4,2,5 As 3 is present at 1st position.
1,2,5,3,4 As 5 is present at 3rd position.
I am not getting any idea to count all possible number of permutations with given condition.
Okay, if we have a guarantee that numbers si are given in not descending order then looks like it is possible to calculate the number of permutations in O(n).
The idea of straightforward algorithm is as follows:
At step i multiply the result by current value of si[i];
We chose some number for position i. As long as we need permutation, that number cannot be repeated, so decrement all the rest si[k] where k from i+1 to the end (e.g. n) by 1;
Increase i by 1, go back to (1).
To illustrate on example for si: 2 3 3 4:
result = 1;
current si is "2 3 3 4", result *= si[0] (= 1*2 == 2), decrease 3, 3 and 4 by 1;
current si is "..2 2 3", result *= si[1] (= 2*2 == 4), decrease last 2 and 3 by 1;
current si is "....1 2", result *= si[2] (= 4*1 == 4), decrease last number by 1;
current si is "..... 1", result *= si[3] (= 4*1 == 4), done.
Hovewer this straightforward approach would require O(n^2) due to decreasing steps. To optimize it we can easily observe that at the moment of result *= si[i] our si[i] was already decreased exactly i times (assuming we start from 0 of course).
Thus O(n) way:
unsigned int result = 1;
for (unsigned int i = 0; i < n; ++i)
{
result *= (si[i] - i);
}
for each si count the number of element in your array such that a[i] <= si using binary search, and store the value to an array count[i], now the answer is the product of all count[i], however we have decrease the number of redundancy from the answer ( as same number could be count twice ), for that you can sort si and check how many number is <= s[i], then decrease that number from each count,the complexity is O(nlog(n)), hope at least I give you an idea.
To complete Yuriy Ivaskevych answer, if you don't know if the sis are in increasing order, you can sort the sis and it will also works.
And the result will be null or negative if the permutations are impossible (ex: 1 1 1 1 1)
You can try backtracking, it's a little hardcore approach but will work.
try:
http://www.thegeekstuff.com/2014/12/backtracking-example/
or google backtracking tutorial C++

Reach John to top

Problem Statement
John wants to climb up a stair of n steps. He can climb 1 or 2 steps at each move. John wants the number of moves to be a multiple of an integer m.
What is the minimal number of steps making him climb to the top of the stairs that satisfies his condition?
Input
The single line contains two space separated integers n, m (0 < n ≤ 10000, 1 < m ≤ 10).
Output
Print a single integer — the minimal steps being a multiple of m. If there is no way he can climb satisfying condition print  - 1 instead.
Sample test(s)
Input
10 2
Output
6
Input
3 5
Output
-1
Notes:
For the first sample, John could climb in 6 moves with following sequence of steps: {2, 2, 2, 2, 1, 1}.
For the second sample, there are only three valid sequence of steps {2, 1}, {1, 2}, {1, 1, 1} with 2, 2, and 3 steps respectively. All these numbers are not multiples of 5.
My code:
I have been trying to solve this problem ,so i thought of using nearest power of 2 less than the given number but got wrong answer
#include<stdio.h>
#include<math.h>
using namespace std;
int main(){
int n,m;
scanf("%d %d",&n,&m);
int x= pow (2,floor (log2(n)) );
int rem = n-x;
int ans = ((x/2)+rem);
if ( ans % m == 0 )
printf (" %d \n ",ans);
else
printf("-1\n");
return 0;
}
I personally don't see how the powers of two are useful at all.
Let's write a different algorithm in pseudocode first:
N = number of steps
M = desired multiple
# Excluding any idea of the multiple restraint, what is the maximum and minimum
# number of steps that John could take?
If number of steps is even:
minimum = N / 2
maximum = N
If number of steps is odd:
minimum = N / 2 + 1
maximum = N
# Maybe the minimum number of steps is perfect?
If minimum is a multiple of M:
Print minimum
# If it isn't, then we need to increase the number of steps up to a multiple of M.
# We then need to make sure that it didn't surpass the maximum number of steps.
Otherwise:
goal = minimum - (minimum % M) + M
if goal <= maximum:
Print goal
Otherwise:
Print -1
We can then convert this to code:
#include <cstdio>
int main(){
int n,m;
scanf("%d %d", &n, &m);
const int minimum = (n / 2) + (n % 2);
const int maximum = n;
if (minimum % m == 0) {
printf("%d\n", minimum);
return 0;
}
const int guess = minimum - (minimum % m) + m;
if (guess <= maximum) {
printf("%d\n", guess);
return 0;
}
printf("%d\n", -1);
return 0;
}
The key tool that I'm using here is that I know that John can scale the stairs in any combination of steps between (and including) [minimum, maximum]. How can we determine this?
We know the minimum number of steps is using 2 at a time as much as possible.
We know the maximum number of steps is using 1 at a time.
We know that if the current number of steps is not the maximum, then we can replace one of the steps (that must be using 2 at a time) and replace it with taking each step one at a time. That would increase the total number of steps by 1.

Dynamic programming algorithm N, K problem

An algorithm which will take two positive numbers N and K and calculate the biggest possible number we can get by transforming N into another number via removing K digits from N.
For ex, let say we have N=12345 and K=3 so the biggest possible number we can get by removing 3 digits from N is 45 (other transformations would be 12, 15, 35 but 45 is the biggest). Also you cannot change the order of the digits in N (so 54 is NOT a solution). Another example would be N=66621542 and K=3 so the solution will be 66654.
I know this is a dynamic programming related problem and I can't get any idea about solving it. I need to solve this for 2 days, so any help is appreciated. If you don't want to solve this for me you don't have to but please point me to the trick or at least some materials where i can read up more about some similar issues.
Thank you in advance.
This can be solved in O(L) where L = number of digits. Why use complicated DP formulas when we can use a stack to do this:
For: 66621542
Add a digit on the stack while there are less than or equal to L - K digits on the stack:
66621. Now, remove digits from the stack while they are less than the currently read digit and put the current digit on the stack:
read 5: 5 > 2, pop 1 off the stack. 5 > 2, pop 2 also. put 5: 6665
read 4: stack isnt full, put 4: 66654
read 2: 2 < 4, do nothing.
You need one more condition: be sure not to pop off more items from the stack than there are digits left in your number, otherwise your solution will be incomplete!
Another example: 12345
L = 5, K = 3
put L - K = 2 digits on the stack: 12
read 3, 3 > 2, pop 2, 3 > 1, pop 1, put 3. stack: 3
read 4, 4 > 3, pop 3, put 4: 4
read 5: 5 > 4, but we can't pop 4, otherwise we won't have enough digits left. so push 5: 45.
Well, to solve any dynamic programming problem, you need to break it down into recurring subsolutions.
Say we define your problem as A(n, k), which returns the largest number possible by removing k digits from n.
We can define a simple recursive algorithm from this.
Using your example, A(12345, 3) = max { A(2345, 2), A(1345, 2), A(1245, 2), A(1234, 2) }
More generally, A(n, k) = max { A(n with 1 digit removed, k - 1) }
And you base case is A(n, 0) = n.
Using this approach, you can create a table that caches the values of n and k.
int A(int n, int k)
{
typedef std::pair<int, int> input;
static std::map<input, int> cache;
if (k == 0) return n;
input i(n, k);
if (cache.find(i) != cache.end())
return cache[i];
cache[i] = /* ... as above ... */
return cache[i];
}
Now, that's the straight forward solution, but there is a better solution that works with a very small one-dimensional cache. Consider rephrasing the question like this: "Given a string n and integer k, find the lexicographically greatest subsequence in n of length k". This is essentially what your problem is, and the solution is much more simple.
We can now define a different function B(i, j), which gives the largest lexicographical sequence of length (i - j), using only the first i digits of n (in other words, having removed j digits from the first i digits of n).
Using your example again, we would have:
B(1, 0) = 1
B(2, 0) = 12
B(3, 0) = 123
B(3, 1) = 23
B(3, 2) = 3
etc.
With a little bit of thinking, we can find the recurrence relation:
B(i, j) = max( 10B(i-1, j) + ni , B(i-1, j-1) )
or, if j = i then B(i, j) = B(i-1, j-1)
and B(0, 0) = 0
And you can code that up in a very similar way to the above.
The trick to solving a dynamic programming problem is usually to figuring out what the structure of a solution looks like, and more specifically if it exhibits optimal substructure.
In this case, it seems to me that the optimal solution with N=12345 and K=3 would have an optimal solution to N=12345 and K=2 as part of the solution. If you can convince yourself that this holds, then you should be able to express a solution to the problem recursively. Then either implement this with memoisation or bottom-up.
The two most important elements of any dynamic programming solution are:
Defining the right subproblems
Defining a recurrence relation between the answer to a sub-problem and the answer to smaller sub-problems
Finding base cases, the smallest sub-problems whose answer does not depend on any other answers
Figuring out the scan order in which you must solve the sub-problems (so that you never use the recurrence relation based on uninitialized data)
You'll know that you have the right subproblems defined when
The problem you need the answer to is one of them
The base cases really are trivial
The recurrence is easy to evaluate
The scan order is straightforward
In your case, it is straightforward to specify the subproblems. Since this is probably homework, I will just give you the hint that you might wish that N had fewer digits to start off with.
Here's what i think:
Consider the first k + 1 digits from the left. Look for the biggest one, find it and remove the numbers to the left. If there exists two of the same biggest number, find the leftmost one and remove the numbers to the left of that. store the number of removed digits ( name it j ).
Do the same thing with the new number as N and k+1-j as K. Do this until k+1 -j equals to 1 (hopefully, it will, if i'm not mistaken).
The number you end up with will be the number you're looking for.