Last week in an interview I was asked the above question and as expected I wasn't able to answer it correctly, later on when I checked I saw that its a dynamic programming based algorithm. I am not proficient in dynamic programming but suppose I was to design this algorithm then how should I approach it?
Suppose, I take idea from other divide and conquer algorithms like MergeSort and design the solution something like:
Divide the sequence in two equal halves.
Find the longest increasing sub-sequence in two halves
Join the two halves.
Obviously there are missing pieces, but how get forward from here?
Your proposal won't work, because the longest sequences in both halves usually won't be contiguous, and there could exist a longer sequence when you join the halves.
You can fix this as follows:
in both halves, find the longest increasing sub-sequence, let L and R;
in both halves, find the longest increasing sub-sequence which is left-aligned, let LL and RL;
in both halves, find the longest increasing sub-sequence which is right-aligned, let LR and RR;
for the longest, keep the longest of L, R, LR+RL if the latter forms an increasing sequence;
for the left-aligned, keep LL or the whole left sub-sequence + RL if this forms an increasing sub-sequence;
for the right-aligned, keep RR or LR + the whole right sub-sequence if this forms an increasing sub-sequence.
All these operations are done in a single recursive process. When you concatenete two sub-sequences, checking if they form an increasing sub-sequence just takes the comparison of the facing elements.
Update:
This "fix" was not thoroughly checked.
Related
How to find the difference between the last and first element of the longest increasing sub-sequence such that value of (last element - first element) in LIS is maximum ?
Let's use a standard dynamic programming solution where we define f[i] as the longest increasing subsequence ending in the i-th element. We can store a pair (max length, smallest first element) for each i instead. One can show that it leads to a correct global solution (intuitively, it's correct as it still stores an optimal solution for all subsequences ending in a specific element and the fact that one prefix is "better" than the other means that the overall subsequence is better).
You can also make it O(N log N) by storing this pairs in an efficient data structure (like a segment tree) if the performance requirements are high.
Very naive algorithm is as follows:
In the first pass find all maximal consecutive subsequences and their length maintain the maximum length (just maintain the number for this).
In the second pass find the start and end differences of all sequences of maximum length and output the one which is maximum among all of them.
All this is in O (n), it is possible to do it in one pass. Just to simplify it I break it down into two steps.
I've seen some discussion about longest monotonically increasing sub-sequence algorithm. But my case is a little bit different.
The double increasing sub-sequence is defined as this:
The first part and second part of the sub-sequence are both monotonically increasing sub-sequences.
For example:
the sequence 10,19,8,12 is;
the sequence 10,19,28,33 is;
the sequence 10,19,28,28 is;
the sequence 10,19,8,2 not;
the sequence 10,19,8,8 not
another sequence that satisfy the condition is:
1,3,5,7,9,10, 6,9,11,17,28,30;
so the first part 1,3,5,7,9,10 is strictly monotonically increasing; and the same for the second part 6,9,11,17,28,30.
The original sequence maybe something like:
1,99,3,98,5,97,7,96,9,95,10, 6,89,9,88,11,87,17,86,28,85,30
Can we find a little-o(n^2)-time algorithm?
Yes, it is even possible to get an O(n log n) solution. Let's assume that we have computed the length of the longest increasing subsequence that ends somewhere to the left(inclusively) from i for each i and the length of the longest decreasing subsequence in a reversed array that to the right from i(not including i). Then the answer is the lagrest sum of these two values for all i. It can be done in O(n log n) time because all what you have to do is to run standard algorithm for computing the longest increasing/decreasing subsequence twice and then make a couple of linear passes.
I am trying to find ALL longest increasing subsequence of an array. I could manage to find one such LIS in O(n log n) using binary search as suggested on Wikipedia.
Can someone help me as how can I extend the same for finding ALL such LIS. I can't find better way of doing it in more than O(n²). Any suggestion to optimization would be really helpful.
Consider this list:
2,1, 4,3, 6,5, 8,7, 10,9, ..., 2m,2m-1
The longest increasing sequence length of this list is m = n/2. You can trivially construct such a sequence by picking one element from each "pair" of items. Since there are m such pairs, and the choices are independent, there are 2^m longest increasing sequences.
So your algorithm can't be faster than Ω(2^(n/2)), because there's at least that much output in some cases.
To get around this you need to tweak the problem, perhaps by doing an output-sensitive analysis or by counting the number of sequences instead of actually generating them. Another alternative is to output a compact way that can be used later to generate all the sequences, which is what linear time unification algorithms do.
There can be exponentially many such sequences. You certainly cannot enumerate them in quadratic time.
You can find, in O(n log(n)) time, the length of the longest increasing subsequences starting and ending at each position in the array. Then you can enumerate all of the longest increasing subsequences by a straightforward recursion.
Given an array string, find the longest substring which is palindrome. For example, if the given string is “forgeeksskeegfor”, the output should be "geeksskeeg".
The problem has an efficient solution with Dynamic Programming.
However, I was just wondering why cant we solve the problem with Divide and Conquer in a similar way we solve the Maximum Subarray problem. (http://en.wikipedia.org/wiki/Maximum_subarray_problem )
We formulate the maximum subarray problem to be efficiently solved with D&C:
1) Divide the given array in two halves
2) Return the maximum of following three
….a) Maximum subarray sum in left half (Make a recursive call)
….b) Maximum subarray sum in right half (Make a recursive call)
….c) Maximum subarray sum such that the subarray crosses the midpoint
The longest Palindrome subsequence problem can be though of as :
1) Divide the given array in two halves
2) Return the maximum of following three
….a) Maximum palindrome sum in left half (Make a recursive call)
….b) Maximum palindrome sum in right half (Make a recursive call)
….c) Maximum palindrome sum such that the subarray crosses the midpoint
We could think about an implementation and say a solution does not exists,but what about the problem structure stops us from thinking a D&C solution?
The approach of Divide and Conquer might work if the string is of the form "13267224".
Here, 6+2+3 = 11 and 7+2+2 = 11
Hence, "326722" is the longest palindromic sum substring. But in the case of character strings eg. "abaccidba", Divide and Conquer won't work.
Consider the following numbers:
9,44,32,12,7,45,31,98,35,37,41,8,20,27,83,64,61,28,39,93,29,92,17,13,14,55,21,66,72,23,73,99,1,2,88,77,3,65,83,84,62,5,11,74,68,76,78,67,75,69,70,22,71,24,25,26.
I try to implement an algorithm to remove the least amount of numbers in the list to make the sequence
a) increasing order
b) decreasing order
I already tried with the shortest and longest subsecuence. Dont want the code, only the explanation or a pseudo code,i can't understand how to solve the problem thanks!
This is a lightly camouflaged Longest increasing (decreasing) subsequence problem. The algorithm to solving your problem is as follows:
Find the longest increasing (decreasing) subsequence in the array
Remove all elements that do not belong to the longest increasing subsequence.
Since the increasing/decreasing subsequence is longest, the amount of numbers that you will remove is the smallest.
Wikipedia article has a nice pseudocode for solving the LIS/LDS problem. You can substitute binary search for a linear one unless the original sequence is 1000+ elements long.
Since it has already been mentioned, I will add my 2 cents. Most probably this will be asked in interview in those circumstances, the running time(efficiency) is a major concern. So the same problem can be tackled with many algorithms depending on the time they take to execute.
The best known algorithm is of order O(nlogn). Other important one can like Dynamic programming paradigm can also be applied to yield a solution of O(n^2).
O(n^2) here
O(nlogn) here