Enumerating all possible permutations when each element belongs to a set - algorithm

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

Related

Search first appearence in matrix under time complexity demands

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)

Analyze the run time of a nested for loops algorithm

Say i have the following code
def func(A,n):
for i = 0 to n-1:
for k = i+1 to n-1:
for l = k+1 to n-1:
if A[i]+A[k]+A[l] = 0:
return True
A is an array, and n denotes the length of A.
As I read it, the code checks if any 3 consecutive integers in A sum up to 0. I see the time complexity as
T(n) = (n-2)(n-1)(n-2)+O(1) => O(n^3)
Is this correct, or am I missing something? I have a hard time finding reading material about this (and I own CLRS)
You have the functionality wrong: it checks to see whether any three elements add up to 0. To improve execution time, it considers them only in index order: i < k < j.
You are correct about the complexity. Although each loop takes a short-cut, that short-cut is merely a scalar divisor on the number of iterations. Each loop is still O(n).
As for the coding, you already have most of it done -- and Stack Overflow is not a coding service. Give it your best shot; if that doesn't work and you're stuck, post another question.
If you really want to teach yourself a new technique, look up Python's itertools package. You can use this to generate all the combinations in triples. You can then merely check sum(triple) in each case. In fact, you can use the any method to check whether any one triple sums to 0, which could reduce your function body to a single line of Python code.
I'll leave that research to you. You'll learn other neat stuff on the way.
Addition for OP's comment.
Let's set N to 4, and look at what happens:
i = 0
for k = 1 to 3
... three k loop
i = 1
for k = 2 to 3
... two k loops
i = 2
for k = 3 to 3
... one k loop
The number of k-loop executions is the "triangle" number of n-1: 3 + 2 + 1. Let m = n-1; the formula is T(m) = m(m-1)/2.
Now, you propagate the same logic to the l loops. You run T(k) loops on l for k= 1, 2, 3. If I recall, this third-order "pyramid" formula is P(m) = m(m-1)(m-2)/6.
In terms of n, this is (n-1)(n-2)(n-3)/6 loops on l. When you multiply this out, you get a straightforward cubic formula in n.
Here is the sequence for n=5:
0 1 2
0 1 3
0 1 4
change k
0 2 3
0 2 4
change k
0 3 4
change k
change k
change l
1 2 3
1 2 4
change k
1 3 4
change k
change k
change l
2 3 4
BTW, l is a bad variable name, easily confused with 1.

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.

Adjacent Bit Counts

here is the problem from spoj that states
For a string of n bits x1,x2,x3,...,Xn
the adjacent bit count of the string
(AdjBC(x)) is given by
X1*X2 + X2*X3 + X3*X4 + ... + Xn-1 *
Xn
which counts the number of times a 1
bit is adjacent to another 1 bit. For
example:
AdjBC(011101101) = 3
AdjBC(111101101) = 4
AdjBC(010101010) = 0
and the question is : Write a program which takes as input integers n and k and returns the number of bit strings x of n bits (out of 2ⁿ) that satisfy AdjBC(x) = k.
I have no idea how to solve this problem. Can you help me to solve this ?
Thanks
Often in combinatorial problems, it helps to look at the set of values it produces. Using brute force I calculated the following table:
k 0 1 2 3 4 5 6
n +----------------------------
1 | 2 0 0 0 0 0 0
2 | 3 1 0 0 0 0 0
3 | 5 2 1 0 0 0 0
4 | 8 5 2 1 0 0 0
5 | 13 10 6 2 1 0 0
6 | 21 20 13 7 2 1 0
7 | 34 38 29 16 8 2 1
The first column is the familiar Fibonacci sequence, and satisfies the recurrence relation f(n, 0) = f(n-1, 0) + f(n-2, 0)
The other columns satisfies the recurrence relation f(n, k) = f(n - 1, k) + f(n - 1, k - 1) + f(n - 2, k) - f(n - 2, k - 1)
With this, you can do some dynamic programming:
INPUT: n, k
row1 <- [2,0,0,0,...] (k+1 elements)
row2 <- [3,1,0,0,...] (k+1 elements)
repeat (n-2) times
for j = k downto 1 do
row1[j] <- row2[j] + row2[j-1] + row1[j] - row1[j-1]
row1[0] <- row1[0] + row2[0]
swap row1 and row2
return row2[k]
As a hint you can split it up into two cases: numbers ending in 0 and numbers ending in 1.
def f(n, k):
return f_ending_in_0(n, k) + f_ending_in_1(n, k)
def f_ending_in_0(n, k):
if n == 1: return k == 0
return f(n - 1, k)
def f_ending_in_1(n, k):
if n == 1: return k == 0
return f_ending_in_0(n - 1, k) + f_ending_in_1(n - 1, k - 1)
This gives the correct output but takes a long time to execute. You can apply standard dynamic programming or memoization techniques to get this to perform fast enough.
I am late to the party, but I have a linear time complexity solution.
For me this is more of a mathematical problem. You can read the detailed solution in this blog post written by me. What follows is a brief outline. I wish I could put some LaTeX, but SO doesn't allows that.
Suppose for given n and k, our answer is given by the function f(n,k). Using Beggar's Method, we can arrive at the following formula
f(n,k) = SUM C(k+a-1,a-1)*C(n-k+1-a,a), where a runs from 1 to (n-k+1)/2
Here C(p,q) denotes binomial coefficients.
So to get our answer, we have to calculate both the binomial coefficients for each value of a. We can calculate the binomial table beforehand. This approach will then given our answer in O(n^2) since we have to calculate the table.
We can improve the time complexity by using the recursion formula C(p,q) = (p * C(p-1,q-1))/q to calculate the current value of binomial coefficients from their values in previous loop.
Our final code looks like this:
long long x=n-k, y=1, p=n-k+1, ans=0;
ans += x*y;
for(int a=2; a<=p/2; a++)
{
x = (x*(p-2*a+1)*(p-2*a+2))/(a*(p-a+1));
y = (y*(k+a-1))/(a-1);
ans += x*y;
}
You can find the complete accepted solution in my GitHub repository.

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