I have a table of dimension m * n as given below
2 6 9 13
1 4 12 21
10 14 16 -1
Few constraints about this table:
Elements in each row is sorted in increasing order (natural
ordering).
A -1 means the cell is of no significance for the purpose of
calculatio, i.e. no element exists there.
No element can appear in a row after a -1.
All the cells can have either a positive number between 0 and N or
a -1.
No two cells have the same positive numbe, i.e. a -1 can appear
multiple times but no other number can.
Question: I would like to find a set S of n numbers from the table where the set must contain only one number from each row and the max(S) - min(S) is as small as possible.
For e.g. the above table gives me S = 12,13,14.
I would really appreciate if this can be solved. My solution is complicated and it takes O(m^n) and this is too much. I want an optimal solution.
Here is a brute force O((m*n)^2 * nlog(m)) algorithm that I can prove works:
min <- INFINITY
For each 2 numbers in different rows, let them be a,b
for each other row:
check if there is a number between a and b
if there is a matching number in every other row:
min <- min{min,|a-b|}
Explanation:
Checking if there is a number between a and b can be done using binary search, and is O(logm)
There are O((n*m)^2) different possibilities for a,b.
The idea is to exhaustively check the pair which creates the maximal difference, and check if it gives a "feasible" solution(all other elements in this solution are in range [a,b]), and get the pair that minimizes the difference between all "feasible" solutions .
EDIT: removed the 2nd solution I proposed, which was greedy and wrong.
Put positions of all first elements of each row into priority queue (min-heap).
Remove smallest element from the queue and replace it with the next element from the same row.
Repeat step 2 until no more elements different from "-1" are left in some row. Calculate max(S) - min(S) for each iteration and if it is smaller than any previous value, update the best-so-far set S.
Time complexity is O(m*n*log(m)).
Related
I would like to find the sequence in a list of numbers where it returns the maximum sum. The restrictions are that it must be at every n interval. For example:
n = 4;
A = [1 4 3 2 9 8 7 6]
The optimal subsequence is therefore 4 + 8 = 12 at positions 1 & 5 (we assume position numbering starts at 0).
My idea:
I know this is a dynamic programming problem. However, I'm not sure how to think about it in terms of a smaller problem. Hope this makes sense. Thanks!
If all the numbers are non negative, it is best to make the subsequence as long as possible to get the maximum sum. The restriction with the interval means, that there are just n possibilities to choose the starting index. In the example you get these four:
1 9
4 8
3 7
2 6
Calculate the sum for each and choose the largest.
You can look to the remainder of the index of the elements by n to divide the elements in subset of element distant n the one from another. Then summing all the elements of each subset, you can find the one that with the higher sum.
The sequence (index in the original array, value) at this point can be easily found.
I mean something like this (pay attention at the indentation)
n=lenght of the inteval;
group[n]=[]
sum[n]=[0,....,0];
for i=0,...,array.lenght-1
k=i%n;
insert the i-th element of the array in group[k];
for j=0,...,n-1
sum[j]=sum of all element in group[j];
max=0;
for k=0,...,n-2
if(sum[k]<sum[k+1])
max=k+1;
for u=0,...,group[max].lenght
index=u*max;
print (index, group[max][u])
I'm not sure this is the approach you are looking for, but maybe it can help you.
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.
There is one important point - We can pick any element any number of
times but the total picked element should be equal to K.
For example - If set of elements is 1 2 3 5 and K = 3 and X = 4.
Then answer is 1 because there is only one way to pick 3 elements which adds upto 4 and those 3 elements are two 1's and one 2. (1+1+2 = 4)
An algorithm can greatly help. :)
Let's consider DP solution for coin change problem.
Usually entries of array A with length (Sum+1) contain integers - number of ways to make the value of every cell.
Simple modification - make 2D array A[Sum+1][K], so A[M][P] will contain number of ways to make value M using P coins.
Let M be an n x n matrix with each entry equal to either 0 or 1. Let m[i][j]
denote the entry in row i and column j. A diagonal entry is one of the
form m[i][i] for some i. Swapping rows i and j of the matrix M denotes the following action:
we swap the values m[i][k] and m[j][k] for k = 1, 2 ..... n. Swapping two columns
is defined analogously We say that M is re arrangeable if it is possible to swap some of the pairs of rows and some of the pairs of columns (in any sequence) so that,
after all the swapping, all the diagonal entries of M are equal to 1.
(a) Give an example of a matrix M that is not re arrangeable, but for
which at least one entry in each row and each column is equal to !.
(b) Give a polynomial-time algorithm that determines whether a matrix
M with 0-1 entries is re-arrangeable.
I tried a lot but could not reach to any conclusion please suggest me algorithm for that.
I think this post is on topic here because I think the answer is http://en.wikipedia.org/wiki/Assignment_problem. Consider the job of putting a 1 in column i, for each i. Each row could do some subset of those jobs. If you can find an assignment of rows such that there is a different row capable of putting a 1 in each column then you can make the matrix diagonal by rearranging the rows so that row i puts a 1 on column i.
Suppose that there is an assignment that solves the problem. Paint the cells that hold the 1s for the solution red. Notice that permuting rows leaves a single red cell in each row and in each column. Similarly permuting columns leaves a single red cell in each row and each column. Therefore no matter how much you permute rows and columns I can restore the diagonal by permuting rows. Therefore if there is any solution which places 1s on all the diagonals, no matter how much you try to disguise it by permuting both rows and columns I can restore a diagonal by permuting only rows. Therefore the assignment algorithm fails to solve this problem exactly when there is no solution, for example if the only 1s are in the top row and the leftmost column.
Two integers N<=10^5 and K<=N are given, where N is the size of array A[] and K is the length of continuous subsequence we can choose in our process.Each element A[i]<=10^9. Now suppose initially all the elements of array are unmarked. In each step we'll choose any subsequence of length K and if this subsequence has unmarked elements then we will mark all the unmarked elements which are minimum in susequence. Now how to calculate minimum number of steps to mark all the elements?
For better understanding of problem see this example--
N=5 K=3
A[]=40 30 40 30 40
Step 1- Select interval [1,3] and mark A[1] and A[3]
Step2- Select interval [0,2] and mark A[0] and A[2]
Step 3- Select interval [2,4] and mark A[4]
Hence minimum number of steps here is 3.
My approach(which is not fast enough to pass)-
I am starting from first element of array and marking all the unmarked elements equal to it at distance <=K and incrementing steps by 1.
First consider how you'd answer the question for K == N (i.e. without any effective restriction on the length of subsequences). Your answer should be that the minimum number of steps is the number of distinct values in the array.
Then consider how this changes as K decreases; all that matters is how many copies of a K-length interval you need to cover the selection set {i: A[i] == n} for each value n present in A. The naive algorithm of walking a K-length interval along A, halting at each position A[i] not yet covered for that value of n is perfectly adequate.
As we see minimum number of steps = N/k or N/k+1 and maximum number of steps =(n+k-1).
We have to optimize the total number of steps and which depend on past history of choices we made which refers to dynamic solution.
For dynamic theory tutorial see http://www.quora.com/Dynamic-Programming/How-do-I-get-better-at-DP-Are-there-some-good-resources-or-tutorials-on-it-like-the-TopCoder-tutorial-on-DP/answer/Michal-Danil%C3%A1k
Can be solved in O(n) as follows:
Trace each element a[i]. If a[i] wasn't traced before then map the number and its index and increase counter.If the number was traced previously then check whether its (last index-curr_index)>=K if yes update the index and increase count. Print count.
Map STL will be beneficial.