count[0] = 1;
for (int x = 1; x <= n; x++) {
for (auto c : coins) {
if (x-c >= 0) {
count[x] += count[x-c];
}
}
}
count[0] = 1;
for (auto c : coins) {
for (int x = 1; x <= n; x++) {
if (x-c >= 0) {
count[x] += count[x-c];
}
}
}
The first piece of code gives the number of possible permutations of each amount, whereas the second gives the combinations, why is this is the case?
The second code updates number of ways to compose values count[i] with new coin. So after k-th round of outer loop we have count[] list filled with combinations of k coins only, and the rest of coins is not used yet. If we remember combinations themselves for sorted coin list, we will see ordered ones like 1 1 5 10 - 5 never will go before 1. That is why combinations.
The first code at m-th round of outer loop fills m-th cell count[m] using all possible coins. So we can get for m=7 both 1 1 5 and 1 5 1 and 5 1 1. That is why all permutations are counted here
Related
how to find the maximum sum of the numbers starting from 1 to n but at any time the current sum should never be equal to a given number k.
This is what I have done but its not correct all the time.
static int maxMoney(int n, long k) {
int currentSum = 0;
for(int i = 1; i <= n; i++){
currentSum += i;
if(currentSum == k){
currentSum -= 1;
continue;
}
}
return currentSum;
}
constraints
1<= n <= 2 * 10^9
1<= k <= 4*10^15
So if n = 3 and k = 3;
and if we add 1 + 2 we get 3, we reject 1 and start at 2 and do 2+3 to get 5.
We can also do 1+3 and we get the value 4 in this case but since we want maximum we choose 5 over 4 and hence 5 is the answer in this case.
Assume first you can just sum all numbers: sum = 1+2+...+n, which can be calculated as sum = n(n+1)/2.
Then check if there is an i between 1 and n, such that 1+2+...+i = k. If not, then the previously calculated sum is the solution.
If there is such i, then reject 1, and return sum - 1.
Determine whether such i exists by solving the following equation:
k = i(i+1)/2
This quadratic equation has this positive solution:
i = (sqrt(1+8k) - 1) / 2
If this i is an integer number, and it is within the interval 1...n, then we have indeed found such an i. Otherwise, we can conclude that k will never be equal to 1+2+...+i for any i in the interval 1...n.
So here is a little JavaScript function that implements this:
function getSum(n, k) {
var sum, i;
sum = n*(n+1)/2;
i = (Math.sqrt(1+8*k) - 1) / 2;
if (i === Math.floor(i) && i <= n)
sum--;
return sum;
}
// Sample call
console.log(getSum(3, 3)); // = 5
So I want to know how to count all the solutions for a knapsack problem. Namely I'm interested in finding the number of possible subsets from a set of numbers that have the maximum size of K.
e.g we have a set of items of size {3, 2, 5, 6, 7} and the max size is K = 13. So the solutions are {5, 6, 2} and {6, 7}. On the other hand there are two solutions; I want my dynamic programming algorithm to report there are two possible solutions.
This can be done with dynamic programming. The basic strategy is to build a memorization table, d[i][j], which stores the number of combinations using the first j numbers that sum to i. Note that j = 0 represents an empty set of numbers. Here is a sample implementation:
int countCombinations(int[] numbers, int target) {
// d[i][j] = n means there are n combinations of the first j numbers summing to i.
int[][] d = new int[target + 1][numbers.length + 1];
// There is always 1 combination summing to 0, namely the empty set.
for (int j = 0; j <= numbers.length; ++j) {
d[0][j] = 1;
}
// For each total i, calculate the effect of using or omitting each number j.
for (int i = 1; i <= target; ++i) {
for (int j = 1; j <= numbers.length; ++j) {
// "First j numbers" is 1-indexed, our array is 0-indexed.
int number = numbers[j - 1];
// Initialize value to 0.
d[i][j] = 0;
// How many combinations were there before considering the jth number?
d[i][j] += d[i][j - 1];
// How many things summed to i - number?
if (i - number >= 0) {
d[i][j] += d[i - number][j - 1];
}
}
}
// Return the entry in the table storing all the number combos summing to target.
return d[target][numbers.length - 1];
}
Just to add some Google keywords: this problem is also known as summing n coins without repeats to a target sum.
There is a dynamic knapsack solution for this task.In dp array dp[i] stores the number of subsets which their sum is "i". In this case your answer is dp[K].( Sorry for indentation problems I could not figure out how to make it right :( )
dp[0] = 1 ;
for( int i=0; i<N ; i++ )
for( int j=K-a[i] ; j>=0 ; j-- )
dp[j+a[i]] += dp[j]
I don't think Max's algorithm works for the case: [0,0,1] with target of 1. The answer is 4 but his algorithm will output 1. His algorithm only works for positive integers, because it assumes that a sum of 0 can only be achieved with empty set. However, it can also be achieved if 0 exists in the array. The more robust way of tackling this problem (and also more space efficient) is using a 1D dp array. The pseudo-code is the following:
int[] dp = new int[target+1];
for (int num : nums) {
for (int s = target; s >= 0; s--) {
if (s >= num) { // can include num
dp[s] += dp[s-num];
} else { // cannot include num (can be omitted, here for better explanation)
dp[s] += 0;
}
}
}
return dp[target+1];
The reason I backtrack from target to 0 in the inner for loop is to avoid duplication. Think about the example [2,2,2] with target sum of 4. If you iterate from index 0, then you would double count a 2 when you are at dp[4] (should be [1 0 1 0 0] instead of [1 0 1 0 1] after one iteration in inner loop).
Hope this helps.
I recently encountered this problem in an interview
There are n stairs, a person standing at the bottom wants to reach the top. The person can climb either 1 stair or 2 stairs at a time.
Print all possible ways person can reach the top.
For example, n=4 Output:
1 2 3 4
1 2 4
1 3 4
2 3 4
2 4
But I couldn't code this properly. How to code up solution for this?
To print the number of ways, you can first understand how to calculate the number of ways, and adjust it so each "count" will print instead of just count:
D(0) = 1
D(-1) = 0
D(i) = D(i-1) + D(i-2)
To adjust it to actual printing, you need to "remember" the choices you have made, and follow the same logic. Pseudo code:
printWays(curr, n, soFar):
if curr > n:
return
soFar.append(curr)
if n == curr:
print soFar
soFar.removeLast()
return
printWays(curr+1,n,soFar)
printWays(curr+2,n,soFar)
soFar.removeLast()
The idea is:
soFar is the current series of steps you did.
curr is the current step you're at.
n is the last stair you need to get to.
At each point, you either climb one stair or two. You check both options.
You can try some recursive solution where you call recursively CanClimb(n-1) and CanClimb(n-2) to visualize the possible ways.
Sample solution in C#:
public static void ClimbWays(int n, int currentIndex, int[] currectClimb)
{
if (n < 0) return;
if (n == 0)
{
for (var i = currentIndex - 1; i >= 0; i--)
{
Console.Write(currectClimb[i] + " ");
}
Console.WriteLine();
return;
}
currectClimb[currentIndex] = n;
ClimbWays(n - 1, currentIndex + 1, currectClimb);
ClimbWays(n - 2, currentIndex + 1, currectClimb);
}
Output for ClimbWays(4, 0, new int[4]);:
1 2 3 4
2 3 4
1 3 4
1 2 4
2 4
If you want to just count them you can use the well known Fibonacci sequence which can be calculated iteratively:
public static int Fibonacci(int n)
{
int a = 0;
int b = 1;
// In N steps compute Fibonacci sequence iteratively.
for (int i = 0; i < n; i++)
{
int temp = a;
a = b;
b = temp + b;
}
return a;
}
Weird question I guess.. But I am not very math wiz - soo here goes..
I am trying to create a patterne (or variable patterns based on selection) based on x and y numbers (2 rows and 4 columns) and the direction of the counting of x numbers
All in PHP ;-)
like:
1-2-3-4
5-6-7-8
That one is easy, when number of x-columns is reached, next line and continue x count.
But with eg. this one (still 2 rows and 4 columns):
1-2-3-4
8-7-6-5
upsie.. what if it is eg. 3++ rows and still 4 columns?
1-2-3-4
8-7-6-5
9-10-11-12
what would be the formula for this - or other possible variations (teaser for variations):
9-10-11-12
8-7-6-5
1-2-3-4
or reversed
For the example you gave where every 2nd row is reversed, use:
int x;
for (int i = 0; i < rowCount; i++)
{
for (int j = 0; j < columnCount; j++)
{
if (i % 2 == 0) // Rows with even index
x = (i * columnCount) + (j+1);
else // Other rows (i.e. odd index)
x = ((i+1) * columnCount) - (j+1);
}
}
You haven't specified a programming language, but the answer looks roughly the same regardless.
I have been trying to formulate an algorithm to solve a problem. In this problem, we have a photo containing some buildings. The photo is divided into n vertical regions (called pieces) and the height of a building in each piece is given.
One building may span several consecutive pieces, but each piece can only contain one visible building, or no buildings at all. We are required to find the minimum number of buildings.
e.g.
given ,
3 ( no of pieces)
1 2 3 ( heights) ans = 3
3
1 2 1 ans = 2
6
1 2 3 1 2 3 ans = 5 ( a figure wud help show the overlap.).
Though I feel like I get it, I am unable to get a solid algorithm for it. Any ideas?
You can find the lowest number from the given array and account for all occurances of this number. This will split the array into multiple subarrays and now you need to recursively solve the problem for each of them.
In the example:
1 2 3 1 2 3 (total = 0)
Smallest number is 1:
x 2 3 x 2 3 (total = 1)
Now you have 2 subarrays.
Solve for the first one - the smallest number is 2:
x 3 (total = 2)
Finally you have a single element: total = 3
Solving the other subarray makes it 5.
Here is some code in C#:
int Solve(int[] ar, int start, int end){
//base for the recursion -> the subarray has single element
if(end-start == 1) return 1;
//base for the recursion -> the subarray is empty
if(end-start < 1) return 0;
//find min
int m = int.MaxValue;
for(int i = start; i < end; i++)
if (ar[i] < m) m = ar[i];
int total = 1;
//find the subarrays and their contribution recursively
int subStart = start;
for(int subEnd = start; subEnd < end; subEnd++){
if(ar[subEnd] == m) {
total += Solve(ar, subStart, subEnd);
subStart = subEnd + 1;
}
}
total += Solve(ar, subStart, ar.Length);
return total;
}