number of valid parenthesis using dynamic programming [Uber phone interview] - algorithm

For given n find the number of valid combinations of valid parenthesis.I told him direct formula of
Catalan number(becuase i encountered this prob earlier) but he specifically wanted this problem Solution using dynamic programming and wanted working solution with explanation with Test cases.I didn't managed to get to the working solution.
Eg:
n=1 valid par=0
n=2 valid par=1
Now I just want to understand this problem
I found one explanation but not getting it Please can you help me in understanding or can you provide
more verbose explanation of below logic (which seems to be correct)
You need even number of paranthesis, if C(n) denotes the number of valid paranthesis with 2 * n paranthesis then
C(0)=1 and for any n>0
C(n)=C(0) * C(n-1)+C(1) * C(n-2)+...+C(n-1) * C(0)=sum(i=0,n-1,C(i) * C(n-1-i))
because you need to start with a '(' and see where is that closing bracket with a ')' if there is 2 * i paranthesis between them then the number of such cases is C(i) * C(n-1-i).

Recursion is the key here.
Divide the N into N/2 and N/2 (Count for open and closed parentheses ).
Select the open parentheses, add it to the result string, and reduce its count and make a recursive call.
Select the close parentheses, add it to the result string, and reduce its count and make a recursive call.
To print only valid parentheses, make sure at any given point of time, close parentheses count is not less than open parentheses count because it means close parentheses have been printed with its respective open parentheses.
Take a look at this link.

M[i][j] dp state.
The length between i - j is always even number.
Then problem is similar to matrix multiplication.
M[i][j] = M[i][i+1]*M[i+2][j] + M[i][i+3]*M[i+4][j] + ..... + M[i][j-2]*M[j-1][j]
Also add the case where i'th parentheses is '(' and j'th parentheses is ')'
M[i][j] += M[i+1][j-1]

Related

Solve using either master theorem or by expansion

I have two questions, which I have trying but unable to figure them out.
1) 𝑇(𝑛) = 𝑇(𝑛 − 1) + 𝑛^4
2) 𝑇(𝑛) = 2𝑇 (𝑛/2) + 𝑛 lg 𝑛
For first one, I am assuming substitution (am I correct?), and got kb + T(n-k). Pretty sure that's wrong so need help with it.
For the second one, I have no idea at all...
Any help would be great! Thanks!
1) So you got
...? I don't know how you obtained this but it's certainly incorrect.
This is basically the summation of the 4th power of all integers up to n. The standard formula for this is:
2) We can find a pattern if we keep expanding this:
The limit log n - 1 is because we keep dividing the parameter to T by 2, so the substitution as above can continue for log n lines until, say T(1) or wherever the stopping condition is. Continuing using the logarithm rules (google them if you don't know):
Both summations have log n terms. Since the 1st summation does not depend on i at all, we simply multiply by log n. The 2nd summation is given by a standard formula for summation of integers from 1 (or 0, doesn't matter in this case):

Maximize evaluation of expression with one parenthesis insertion

I encountered this problem in a programming contest:
Given expression x1 op x2 op x3 op . . . op xn, where op is either addition '+' or multiplication '*' and xi are digits between 1 to 9. The goal is to insert just one set of parenthesis within the expression such that it maximizes the result of the expression.
The n is maximum 2500.
Eg.:
Input:
3+5*7+8*4
Output:
303
Explanation:
3+5*(7+8)*4
There was another constraint given in the problem that at max only 15 '*' sign will be present. This simplified the problem. As we will have just 17 options of brackets insertion and brute force would work in O(17*n).
I have been thinking if this constraint was not present, then can I theoretically solve the problem in O(n^2)? It seemed to me a DP problem. I am saying theoretically because the answers will be quite big (9^2500 possible). So if I ignore the time complexity of working with big numbers then is O(n^2) possible?
If there is no multiplication, you are finished.
If there is no addition, you are finished.
The leading and trailing operation of subterms that have to be evaluated always are additions, because parenthesis around a multiplication does not alter the outcome.
If you have subterms with only additions, you do not need to evaluate subparts of them. Multiplication of the full subterm will always be bigger. (Since we only have positiv numbers/digits.)
Travers the term once, trying to place the opening parenthesis after (worst case) each * that is succeeded with a +, and within that loop a second time, trying to place the closing parenthesis before (worst case) each succeeding * that immediately follows an +.
You can solve the problem in O(ma/2), with m: number of multiplications and a: number of additions. This is smaller than n^2.
Possible places for parenthesis shown with ^:
1*2*^3+4+5^*6*^7+8^

Balanced Parenthesis Order number

Suppose if you consider the case of length-six strings, the order would be: “()()()”, “()(())”, “(())()”, “(()())”, “((()))”.
In the above example, if we see that the strings in which the first opening parenthesis is closed the earliest come first, and if that is the same for two strings, the rule is recursively applied to the next opening parenthesis.
If particular balanced parenthesis sequence is given how to find the order number? Suppose ()(())--> Output is 2....In O(n) where n is the length of balanced parenthesis i.e 3 in above case...The input can be around 100000 balanced parenthesis
First let g(n,k) be the number of length 2n + k strings there are with n pairs of balanced parentheses, which close k more parentheses. Can we calculate g(n,k)?
Let's try recursion. For that we first need a base case. It is clear that if there are no balanced parentheses, then we can only have one possibility - only closing parentheses. So g(0,k) = 1. There is our base case.
Next the recursive case. The first character is either an opening parenthesis, or a closing parenthesis. If it is an opening parenthesis, then there are g(n-1,k+1) ways to finish. If it is a closing parenthesis, then there are g(n,k-1) ways to finish. But we can't have a negative number of open
g(0,k) = 1
g(n,-1) = 0
g(n,k) = g(n-1, k+1)
This lets us calculate g but is not efficient - we are effectively going to list every possible string in the recursive calls. However there is a trick, memoize the results. Meaning that every time you call g(n, k) see if you've ever called it before, and if you have just return that answer. Otherwise you calculate the answer, cache it, and then return it. (For more on this trick, and alternate strategies, look up dynamic programming.)
OK, so now we can generate counts of something related, but how can we use this to get your answer?
Well note the following. Suppose that partway through your string you find an open parenthesis where there logically could be a close parenthesis instead. Suppose that at that point there are n pairs of parentheses needed and k open parentheses. Then there were g(n, k-1) possible strings that are the same as yours until then, then have a close parenthesis there (so they come before yours) and do whatever afterwards. So summing g(n, k-1) over all of the close parentheses gives you the number of strings before yours. Adding one to that gives you your position.
I got the answer from the Ruskey thesis. This algorithm specified about the Ranking & unranking of binary trees.
http://webhome.cs.uvic.ca/~ruskey/Publications/Thesis/ThesisPage16.png

Linear algorithm on binary strings

I'm going through some old midterms to study. (None of the solutions are given)
I've come across this problem which I'm stuck on
Let n = 2ℓ − 1 for some positive integer ℓ. Suppose someone claims to hold an array A[1.. n] of
distinct ℓ-bit strings; thus, exactly one ℓ-bit string does not appear in A. Suppose further that the
only way we can access A is by calling the function FetchBit(i, j), which returns the jth bit of the string A[i] in O(1) time.
Describe an algorithm to find the missing string in A using only O(n) calls to FetchBit.
The only thing I can think of is go through each string, convert it to base 10, sort them all and then see which value is missing. But that's certainly not O(n)
Proof it's not homework... http://web.engr.illinois.edu/~jeffe/teaching/algorithms/hwex/f12/midterm1.pdf
You can do it in 2n operations.
First, look at the first bit of every number. Obviously, you will get 2ℓ-1 zeros and 2ℓ-1-1 ones ore vice versa (because only one number is missing). If there is 2ℓ-1-1 ones then you know that the first bit of the missing number is one, otherwise it is zero.
Now you know the first bit of a missing number. Let's look at all numbers which have the same first bit (there are 2ℓ-1-1 of them) and repeat the same procedure with their second bit. This way you will determine the second bit of the missing number, and so on.
The total number of FetchBit calls will be 2ℓ-1 + 2ℓ-1-1 + ... + 21-1 <= 2ℓ+1 <= 2n+2 = O(n).

Algorithm to find lenth of longest sequence of blanks in a given string

Looking for an algorithm to find the length of longest sequence of blanks in a given string examining as few characters as possible?
Hint : Your program should become faster as the length of the sequence of blanks increases.
I know the solution which is O(n).. But looking for more optimal solution
You won't be able to find a solution which is a smaller complexity than O(n) because you need to pass through every character in the worst case with an input string that has at most 0 or 1 consecutive whitespace, or is completely whitespace.
You can do some optimizations though, but it'll still be considered O(n).
For example:
Let M be the current longest match so far as you go through your list. Also assume you can access input elements in O(1), for example you have an array as input.
When you see a non-whitespace you can skip M elements if the current + M is non whitespace. Surely no whitespace longer than M can be contained inside.
And when you see a whitepsace character, if current + M-1 is not whitespace you know you don't have the longest runs o you can skip in that case as well.
But in the worst case (when all characters are blank) you have to examine every character. So it can't be better than O(n) in complexity.
Rationale: assume the whole string is blank, you haven't examined N characters and your algorithms outputs n. Then if any non-examined character is not blank, your answer would be wrong. So for this particular input you have to examine the whole string.
There's no way to make it faster than O(N) in the worst case. However, here are a few optimizations, assuming 0-based indexing.
If you already have a complete sequence of L blanks (by complete I mean a sequence that is not a subsequence of a larger sequence), and L is at least as large as half the size of your string, you can stop.
If you have a complete sequence of L blanks, once you hit a space at position i check if the character at position i + L is also a space. If it is, continue scanning from position i forwards as you might find a larger sequence - however, if you encounter a non-space until position i + L, then you can skip directly to i + L + 1. If it isn't a space, there's no way you can build a larger sequence starting at i, so scan forwards starting from i + L + 1.
If you have a complete sequence of blanks of length L, and you are at position i and you have k positions left to examine, and k <= L, you can stop your search, as obviously there's no way you'll be able to find anything better anymore.
To prove that you can't make it faster than O(N), consider a string that contains no spaces. You will have to access each character once, so it's O(N). Same with a string that contains nothing but spaces.
The obvious idea: you can jump by K+1 places (where K is the current longest space sequence) and scan back if you found a space.
This way you have something about (n + n/M)/2 = n(M+1)/2M positions checked.
Edit:
Another idea would be to apply a kind of binary search. This is like follows: for a given k you make a procedure that checks whether there is a sequence of spaces with length >= k. This can be achieved in O(n/k) steps. Then, you try to find the maximal k with binary search.
Edit:
During the consequent searches, you can utilize the knowledge that the sequence of some length k already exist, and start skipping at k from the very beginning.
What ever you do, the worst case will always be o(n) - if those blanks are on the last part of the string... (or the last "checked" part of the string).

Resources