Search first appearence in matrix under time complexity demands - algorithm

I need to write a psuedo code for an algorithm that gets as an input a matrix (n x m) and outputs the row index of the first appearence of 0
I should describe two algorithms which one of them performs in O(mlogn) and the second one performs in O(m+n)
Special attribute of the matrix :
The matrix consists only of 0 and 1.
Once a zero value is entered all of the same column below that cell needs to be zero aswell.
Example for valid input:
1 1 1 1 1 1
1 0 1 1 1 1
1 0 0 1 0 1
1 0 0 0 0 1
0 0 0 0 0 0
The output should be : 1
Edit : I was able to come up with an algorithm with O(mlogn).

1st algorithm O(m*log(n))
Inside a column the values are sorted in descending order. This means you can find the first 0 in O(log(n)) by using a binary-search inside the column.
There are m columns to search. This leads to O(m*log(n)) to search all columns for their first 0. Finding the first 0 among those m results is O(m) which is dominated by the O(m*log(n)) of the previous search.
2nd algorithm O(m+n)
The second algorithm start from the cell at (n,m). For each column, starting from the last, we go up while we are on a cell with a 0. When we hit a 1 we move to the previous column.
i <- n
j <- m
r <- (-1, -1)
while (j >= 0):
if M(i,j) == 1:
j <- j-1
continue
while (i >= 0 && M(i,j) == 0)
r <- (i,j)
i <- i-1
At the end the result is in r or there was no result at all and r = (-1,-1)

Edit: This answer was for the old question which didn't include the Special attribute of the matrix
I don't think it's possible to come up with an algorithm that performs better than O(mn) in the worst case.
Here is a naive solution that checks each element of the matrix.
def solve(mat, n, m):
for i in range(1, n):
for j in range(i, m):
if mat[i][j] == 0:
return i
return -1
In the worst case (eg when there are no 0s in the input matrix):
The outer for loop will run n times and for each iteration, the inner for loop will run m times.
So the total time complexity will be O(m * n)

Related

Maximum OR value of 2D Array of bits

Suppose there is a 2D array (m x n) of bits.
For example:
1 0 0 1 0
1 0 1 0 0
1 0 1 1 0
0 0 0 0 1
here, m = 4, n = 5.
I can flip (0 becomes 1, 1 becomes 0) the bits in any row. When you flip the bits in a particular row, you flip all the bits.
My goal is to get the max OR value between a given pair of rows.
That is, if the given pair of rows is (r1, r2), then I can flip any number of rows between r1 and r2, and I should find the maximum possible OR value of all the rows between r1 and r2.
In the above example (consider arrays with 1-based index), if r1 = 1 and r2 = 4, I can flip the 1st row to get 0 1 1 0 1. Now, if I find the OR value of all the rows from 1 to 4, I get the value 31 as the maximum possible OR value (there can be other solutions).
Also, it would be nice to to compute the answer for (r1, r1), (r1, r1+1), (r1, r1+2), ... , (r1, r2-1) while calculating the same for (r1,r2).
Constraints
1 <= m x n <= 10^6
1 <= r1 <= r2 <= m
A simple brute force solution would have a time complexity of O(2^m).
Is there a faster way to compute this?
Since A <= A | B, the value of a number A will only go up as we OR more numbers to A.
Therefore, we can use binary search.
We can use a function to get the maximum between two rows and save the ORed result as a third row. Then compare two of these third rows to get a higher-level row, and then compare two of these higher-level rows, and so on, until only one is left.
Using your example:
array1 = 1 0 0 1 0 [0]
1 0 1 0 0 [1]
1 0 1 1 0 [2]
0 0 0 0 1 [3]
array2 = 1 1 0 1 1 <-- [0] | ~[1]
1 1 1 1 0 <-- [2] | ~[3]
array3 = 1 1 1 1 1 <-- [0] | [1]
And obviously you can truncate branches as necessary when m is not a power of 2.
So this would be O(m) time. And keep in mind that for large numbers of rows, there are likely not unique solutions. More than likely, the result would be 2 ^ n - 1.
An important optimization: If m >= n, then the output must be 2 ^ n - 1. Suppose we have two numbers A and B. If B has k number missing bits, then A or ~A will be guaranteed to fill at least one of those bits. By a similar token, if m >= log n, then the output must also be 2 ^ n - 1 since each A or ~A is guaranteed to fill at least half of the unfilled bits in B.
Using these shortcuts, you can get away with a brute-force search if you wanted. I'm not 100% the binary search algorithm works in every single case.
Considering the problem of flipping the rows in the entire matrix and then or-ing them together to get as many 1s as possible, I claim this is tractable when the number of columns is less than 2^m, where m is the number of rows. Consider the rows one by one. At stage i counting from 0 you have less than 2^(m-i) zeros to fill. Because flipping a row turns 0s into 1s and vice versa, either the current row or the flipped row will fill in at least half of those zeros. When you have worked through all the rows, you will have less than 1 zeros to fill, so this procedure is guaranteed to provide a perfect answer.
I claim this is tractable when the number of columns is at least 2^m, where m is the number of rows. There are 2^m possible patterns of flipped rows, but this is only O(N) where N is the number of columns. So trying all possible patterns of flipped rows gives you an O(N^2) algorithm in this case.

Enumerating all possible permutations when each element belongs to a set

Problem: You are given a natural number N and a set of elements of size M. Your task is to generate all possible values of a list of size N where each element belongs to set M (both with or without repetition).
Example: Let N = 2 and M = < 0, 1 >.
With repetition: N = [0,1] or N = [1,0] or N = [0,0] or N = [1,1]
Without repetition: N = [1,0] or N = [0,1]
I came up with solution (EDIT - which is wrong) for with repetition as follows.
It is in pseudocode so that it isn't biased to anyone without knowledge of the language.
Let I be an auxillary list of size N.
Let l denote the last value changed in I initialized as value N.
Fill I with value 1.
while l != 0
for i = 1 to N
N[i] = M[I[i]]
do_something(N)
if I[l] != M
I[l] += 1
elseif l == 1
break // So that it does not become not defined in else clause
else
l -= 1
I[l] += 1
It takes O(N^2 * M) time and O(N + M) space. If you have better one then please post it.
I was not able to come up with a good solution for without repetition case.
You would see that your algorithm has a problem if you had actually tried it on some very simple cases, like for example the one you actually gave as an example, with M=N=2. (Why didn't you do this first?) It will not generate the list 1 0.
Why? Because after decrementing l and incrementing the new I[l], you never decrease any of the later (further to the right) values in I[]. So e.g. for N=5 you would generate only the permutations
0 0 0 0 0
0 0 0 0 1
0 0 0 1 1
0 0 1 1 1
0 1 1 1 1
1 1 1 1 1

Count number of ways to divide a number in 4 parts

Given a positive integer n, find number of ways to divide n in four parts or represent n as sum of four positive integers. Here n varies from 0 to 5000.
def foo(target, k, j):
count = 0
map = {}
if target in map.keys() and map[target] == k:
return map[target]
if target == 0 and k == 0:
return 1
if target <= 0 or k < 0:
return 0
for i in range(j, target+1):
count += foo(target-i, k-1, i)
map[target] = count
return count
print(foo(10, 4, 1))
I have solved this problem with above recursive solution but I just saw someone with below dynamic programming solution.
f(0,0) = 1
f(target, k) = 0 if k > target or (target > 0 and k = 0)
f(target, k) = f(target-k, k) + f(target-1, k-1)
Can someone enlighten me on this solution?
That solution is correct but a little bit tricky, and I will try my best to illustrate it clearly to you.
If target=25 and we split it into 25=9+7+5+4. And we express it by 4 columns(1*9, 1*7, 1*5, 1*4):
But in another perspective, you can view the image as 9 rows(1*4, 1*4, 1*4 , 1*4, 1*3, 1*2, 1*2, 1*1, 1*1).
So, you will find your solution is constructing the image by column ways, and that solution is by row ways.
So we come to that solution for details:
f(target, k) = f(target-k, k) + f(target-1, k-1)
f(target, k): target tiles remain and the length of the row is k
f(target - k, k): put a row of length k
f(target - 1, k - 1): put just one tile to rightest column(ensuring the answer is positive integer), and decrease the length of the row by 1.
That's all.
If you still got any question, you may leave a comment here.
Given a number n, find the number of ways you can represent n as sum of x1+x2+x3+x4 such that xi>=0
The answer will be (n+3)C(3)
In general, x1+x2+x3+...+xn=k with xi>=0 has the solution (k+n-1)C(n-1)
Here, k=n and n=4.

Number of binary n x m matrices modulo c, with at most k consecutive number of 1 in each column

I am trying to compute the number of nxm binary matrices with at most k consecutive values of 1 in each column. After a few researches, I've figured out that it will be enough to find the vectors with 1 column and n lines. For example, if we have p number of vectors the required number of matrices would be m^p.
Because n and m are very large (< 2.000.000) i can't find a suitable solution. I am trying to find a recurrence formula in order to build a matrix to help me compute the answer. So could you suggest me any solution?
There's a (k + 1)-state dynamic program (state = number of previous 1s, from 0 to k). To make a long story short, you can compute large terms of it quickly by taking the nth power of the k + 1 by k + 1 integer matrix like (example for k = 4)
1 1 0 0 0
1 0 1 0 0
1 0 0 1 0
1 0 0 0 1
1 0 0 0 0
modulo c and summing the first row.

Rectangular region in an array

Given an N*N matrix having 1's an 0's in them and given an integer k,what is the best method to find a rectangular region such that it has k 1's in it ???
I can do it with O(N^3*log(N)), but sure the best solution is faster. First you create another N*N matrix B (the initial matrix is A). The logic of B is the following:
B[i][j] - is the number of ones on rectangle in A with corners (0,0) and (i,j).
You can evaluate B for O(N^2) by dynamic programming: B[i][j] = B[i-1][j] + B[i][j-1] - B[i-1][j-1] + A[i][j].
Now it is very easy to solve this problem with O(N^4) by iterating over all right-bottom (i=1..N, j=1..N, O(N^2)), left-bottom (z=1..j, O(N)), and right-upper (t=1..i, O(N)) and you get the number of ones in this rectangular with the help of B:
sum_of_ones = B[i][j] - B[i][z-1] - B[t-1][j] + B[t-1][z-1].
If you got exactly k: k==sum_of_ones, then out the result.
To make it N^3*log(N), you should find right-upper by binary search (so not just iterate all possible cells).
Consider this simpler problem:
Given a vector of size N containing only the values 1 and 0, find a subsequence that contains exactly k values of 1 in it.
Let A be the given vector and S[i] = A[1] + A[2] + A[3] + ... + A[i], meaning how many 1s there are in the subsequence A[1..i].
For each i, we are interested in the existence of a j <= i such that S[i] - S[j-1] == k.
We can find this in O(n) with a hash table by using the following relation:
S[i] - S[j-1] == k => S[j-1] = S[i] - k
let H = an empty hash table
for i = 1 to N do
if H.Contains (S[i] - k) then your sequence ends at i
else
H.Add(S[i])
Now we can use this to solve your given problem in O(N^3): for each sequence of rows in your given matrix (there are O(N^2) sequences of rows), consider that sequence to represent a vector and apply the previous algorithm on it. The computation of S is a bit more difficult in the matrix case, but it's not that hard to figure out. Let me know if you need more details.
Update:
Here's how the algorithm would work on the following matrix, assuming k = 12:
0 1 1 1 1 0
0 1 1 1 1 0
0 1 1 1 1 0
Consider the first row alone:
0 1 1 1 1 0
Consider it to be the vector 0 1 1 1 1 0 and apply the algorithm for the simpler problem on it: we find that there's no subsequence adding up to 12, so we move on.
Consider the first two rows:
0 1 1 1 1 0
0 1 1 1 1 0
Consider them to be the vector 0+0 1+1 1+1 1+1 1+1 0+0 = 0 2 2 2 2 0 and apply the algorithm for the simpler problem on it: again, no subsequence that adds up to 12, so move on.
Consider the first three rows:
0 1 1 1 1 0
0 1 1 1 1 0
0 1 1 1 1 0
Consider them to be the vector 0 3 3 3 3 0 and apply the algorithm for the simpler problem on it: we find the sequence starting at position 2 and ending at position 5 to be the solution. From this we can get the entire rectangle with simple bookkeeping.

Resources