I have a n x n array. Each field has a cost associated with it (a natural number) and I here's my problem:
I start in the first column. I need to find the cheapest way to move through an array (from any field in the first column to any in the last column) following these two rules:
I can only make moves to the right, to the top right, the lower right an to the bottom.
In a path I can only make k (some constant) moves to the bottom.
Meaning when I'm at cell x I can moves to these cells o:
How do I find the cheapest way to move through an array? I thought of this:
-For each field of the n x n array I keep a helpful array of how many bottom moves it takes to get there in the cheapest path. For the first column it's all 0's.
-We go through each of the field in this orded : columns left to right and rows top to bottom.
-For each field we check which of their neighbours is 'the cheapest'. If it's the upper one (meaning we have to take a bottom route to get from him) we check if it took k bottom moves to get to him, if not then then we assign the cost of getting to analyzed field as the sum of getting to field at the top+cost of the field, and in the auxilary array for the record corresponding to the field the put the number of bottom moves as x+1, where x is how many bottom moves we took to get to his upper neightbour.
-If the upper neighbour is not the cheapest we assign the cost of the other cheapest neighbour and the number of bottom moves as the number of moves we took to get to him.
Time complexity is O(n^2), and so is memory.
Is this correct?
Here is DP solution in O(N^2) time and O(N) memory :-
Dist(i,j) = distance from point(i,j) to last column.
Dist(i,j) = cost(i,j) + min { Dist(i+1,j),Dist(i,j+1),Dist(i+1,j+1),Dist(i-1,j+1) }
Dist(i,N) = cost[i][N]
Cheapest = min { D(i,0) } i in (1,M)
This DP equation suggests that you need only values of next rows to get current row so O(N) space for maintaining previous calculation. It also suggests that higher row values in same column need to evaluated first.
Pseudo Code :-
int Prev[N],int Curr[N];
// last row calculation => Base Case for DP
for(i=0;i<M;i++)
Prev[i] = cost[i][N-1];
// Evaluate the rows and columns in descending manner
for(j=N-2;j>=0;j--) {
for(i=M-1;i>=0;i--) {
Curr[i][j] = cost[i][j] + min ( Curr[i+1][j],Prev[i][j+1],Prev[i-1][j+1],Prev[i+1][j+1] )
}
Prev = Curr
}
// find row with cheapest cost
Cheapest = min(Prev)
Related
Given a list of n houses, each house has a certain number of coins in it. And a target value t. We have to find the minimum number of steps required to reach the target.
The person can choose to start at any house and then go right or left and collect coins in that direction until it reaches the target value. But the person cannot
change the direction.
Example: 5 1 2 3 4 These are supposed the coin values in 5 houses and the target is 13 then the minimum number of steps required is 5 because we have to select all the coins.
My Thoughts:
One way will be for each index i calculate the steps required in left or right direction to reach the target and then take the minimum of all these 2*n values.
Could there be a better way ?
First, let's simplify and canonize the problem.
Observation 1: The "choose direction" capability is redundant, if you choose to go from house j to house i, you can also go from i to j to have the same value, so it is sufficient to look at one direction only.
Observation 2: Now that we can look at the problem as going from left to right (observation 1), it is clear that we are looking for a subarray whose value exceeds k.
This means that we can canonize the problem:
Given an array with non negative values a, find minimal subarray
with values summing k or more.
There are various ways to solve this, one simple solution using a sorted map (balanced tree for example) is to go from left to right, summing values, and looking for the last element seen whose value was sum - k.
Pseudo code:
solve(array, k):
min_houses = inf
sum = 0
map = new TreeMap()
map.insert(0, -1) // this solves issue where first element is sufficient on its own.
for i from 0 to array.len():
sum = sum + array[i]
candidate = map.FindClosestLowerOrEqual(sum - k)
if candidate == null: // no matching sum, yet
continue
min_houses = min(min_houses, i - candidate)
map.insert(sum, i)
return min_houses
This solution runs in O(nlogn), as each map insertion takes O(logn), and there are n+1 of those.
An optimization, running in O(n), can be done if we take advantage of "non negative" trait of the array. This means, as we go on in the array - the candidate chosen (in the map seek) is always increasing.
We can utilize it to have two pointers running concurrently, and finding best matches, instead of searching from scratch in the index as we did before.
solve(array, k):
left = 0
sum = 0
min_houses = infinity
for right from 0 to len(array):
sum = sum + array[right]
while (left < right && sum >= k):
min_houses = min(min_houses, right - left)
sum = sum - array[left]
left = left + 1
return min_houses
This runs in O(n), as each index is increased at most n times, and every operation is O(1).
I am trying to work through this question in LeetCode.
119. Pascal's Triangle II
Given a non-negative index k where k ≤ 33, return the kth index row of the Pascal's triangle.
Note that the row index starts from 0.
In Pascal's triangle, each number is the sum of the two numbers directly above it.
Example:
Input: 3
Output: [1,3,3,1]
Follow up:
Could you optimize your algorithm to use only O(k) extra space?
import java.util.Arrays;
class Solution {
public List<Integer> getRow(int rowIndex) {
Integer[] dp = new Integer[rowIndex+1];
Arrays.fill(dp,1);
for(int i = 2; i <= rowIndex;i++){
for(int j = i- 1; j > 0;j--){
dp[j] = dp[j-1] + dp[j];
}
}
return Arrays.asList(dp);
}
}
And I see some one giving this working solution.
I can understand why it is correct.
But I am still quite unclear why the array is updating in this order.
In this case I know the transition of status is like:
P(n) = P(n-1) + P(n)
But how can this give clues on how to choose the direction of updating the array?
Why exactly the ascending order doesn't work in this case if we think in the way of DP. I know substantially this could cause duplicated calculation.
I know this may be subtle but still how anyone could at least cast even a little light on that.
Possibly the formula Pn = Pn-1 + Pn brings confusion, as it is not a true recurrence relationship. If it were, it would be infinite.
The true recurrence relationship is given by:
Prow, n = Prow-1, n-1 + Prow-1, n
Or in more complete terms:
∀ n ∈ {1, row-1}: Prow, n = Prow-1, n-1 + Prow-1, n
Prow, 0 = 1
Pn, n = 1
If you would implement this naively, you would create a 2-dimensional DP matrix. Starting with row 0, you would build up the DP matrix going from one row to the next, using the above recurrence relationship.
You then find that you only need the previous row's DP data to calculate the current row's. All the DP rows that come before the previous one are idle: they don't serve any purpose anymore. They are a waste of space.
So then you decide to not create a whole DP matrix, but just two rows. Once you have completed the second row of this DP structure, you make that row the first, and reset the second row in the DP structure. And then you can continue filling that second row, until it is complete again, and you repeat this "shift" of rows...
And now we come to the last optimisation, which brings us to your question:
You can actually do it with one DP row. That row will represent both the previous DP row as the current. For that to work, you need to update that row from right to left.
Every value that is updated is considered "current row", and every value that you read is considered "previous row". That way the right side of the recurrence relation refers to the previous DP row, and the left side (that is assigned) to the current.
This works only from right to left, because the recurrence formula never refers to n+1, but to n at the most. If it would have referred to n and n+1, then you would have had to go from left to right.
At the moment we read the value at n, it is still the value that corresponds to the previous DP row, and once we write to it, we will not need that previous value anymore. And when we read the value at n-1 we are sure it is still the previous row's value, since we come from the right, and did not update it yet.
You can imagine how we wipe-and-replace the values of the "previous" row with the new values of the "current" row.
Hope this clarifies it a bit.
Assume we have an array with n Elements ( n%3 = 0).In each step, a number is taken from the array. Either you take the leftmost or the rightmost one. If you choose the left one, this element is added to the sum and the two right numbers are removed and vice versa.
Example: A = [100,4,2,150,1,1], sum = 0.
take the leftmost element. A = [4,2,150] sum = 0+100 =100
2.take the rightmost element. A = [] sum = 100+150 = 250
So the result for A should be 250 and the sequence would be Left, Right.
How can I calculate the maximum sum I can get in an array? And how can I determine the sequence in which I have to extract the elements?
I guess this problem can best be solved with dynamic programming and the concrete sequence can then be determined by backtracking.
The underlying problem can be solved via dynamic programming as follows. The state space can be defined by letting
M(i,j) := maximum value attainable by chosing from the subarray of
A starting at index i and ending at index j
for any i, j in {1, N} where `N` is the number of elements
in the input.
where the recurrence relation is as follows.
M(i,j) = max { M(i+1, j-2) + A[i], M(i+2, j-1) + A[j] }
Here, the first value corresponds to the choice of adding the beginning of the array while the second value connesponds to the choice of subtracting the end of the array. The base cases are the states of value 0 where i=j.
Consider a game where the game board is a grid with n rows and m columns. You begin at the bottom left corner of the grid (assume this has coordinates (0,0)). You start with a score of 0, and inventory space I > 0.
At each cell of the grid there may be one of two things, the cell is either empty, or contains some loot. Loot has a size x and value v, you can think of each potential piece of loot being indexed by the cell, i.e. L(i,j) = (x(i,j), v(i,j)), where L(i,j) = (0, 0) if the cell is empty.
From cell (i, j) the player can move up 1 row to one of three cells, (i + 1, j − 1), (i + 1, j), or (i + 1, j + 1). The player cannot move back down the rows or move side to side. When the player reaches a cell with loot they can either choose to take it or leave it. Taking it the loot decreases the players inventory space by the size x, while increasing their score by the value v.
How would a dynamic programming algorithm apply to this?
I figure that the subproblems would be moving up the row, where as long as there is a row above, and one of the left/right each. It would choose whichever one has the highest value v and fits in our inventory x, otherwise it just leaves it.
there is N x N sized array filled with random number (-100 <= x <= 100)
starting from A[0][0],
it moves to adjacent indices by stages.
Restriction.
Can't move to visited index.
Can't go upside.
I have to get the biggest value when it finishes moving to A[N-1][N-1].
values in indices that i've visited should be added to the sum
what is the methodology to approach this problem?
[edit]
A more compact statement of a problem: given a square N*N matrix, find the maximum sum of the visited elements along any exploration path passing through adjacent nodes (no diagonals) starting from [0][0] and ending in [N-1][N-1] within the restrictions of:
when changing rows, row index will always increase
while on a row, col index will always either decrease or increase (i.e the path does not backtrack on already visited nodes)
You need a 2D state D[i][j], which keeps track of the maximum sum just before leaving row i at column j. The first row is easy to fill - it is just the prefix sum of the matrix' first row.
For all subsequent rows, you can use the following idea: You may have left the previous row at any column. If you know the exit column of the previous row and the exit column of the current row (defined by the state you want to calculate), you know that the sum consists of the accumulated value at the previous row's exit column plus all the values in the current row between the two exit columns. And from all possible exit columns of the previous row, choose the one that results in the maximum sum:
D[i][j] = max_k (D[i - 1][k] + Sum{m from j to k} A[i][m])
Note that this sum can be calculated incrementally for all possible k. The notation Sum{m from j to k} should also be valid for k smaller than j, which then means to traverse the row backwards.
Calculate these states row by row until you end up at D[N-1][N-1], which then holds the solution for your problem.