Finding a maximal sorted subsequence - algorithm

Assume that we're given a set of pairs S={(x_1,y_1),...,(x_n,y_n)} of integers. What is the most efficient way of computing a maximal sequence of elements (a_1,b_1),...,(a_m,b_m) in S with the property that
a_i <= a_{i+1}
b_i <= b_{i+1}
for i=1,...,m-1, i.e. the sequence is ordered with respect to both components. I can come up with a quadratic algorithm that does the following:
We sort the elements of S with respect to the first coordinate, giving (c_1,d_1),...,(c_n,d_n), where c_i <= c_{i+1}.
Using dynamic programming, for each (c_i,d_i) we compute the longest sequence ordered with respect to both components that ends in (c_i,d_i). This can be done in linear time, once we know the longest such sequence for (c_1,d_1)...,(c_{i+1},d_{i+1}).
Since we have to perform an O(nlogn) sort in step 1 and a linear search for each index in step 2, which is quadratic, we end up with a quadratic runtime.
I've been trying to figure out whether there's a faster, i.e. O(nlogn) way of generating the maximal sequence from having two sorts of the set S: one with respect to the first component, and one with respect to the second. Is this possible?

Yes, it is possible to do it O(n log n).
Let's sort the elements of the set in lexicographical order. The first components are ordered correctly now, so we can forget about them.
Let's take a look at any sorted subsequence of this sorted sequence. The second elements form an increasing subsequence. That's why we can just find the longest increasing subsequence in the sorted sequence for the second element of each pair(completely ignoring first elements as they are already sorted properly). The longest increasing subsequence for an array of numbers can be found in O(n log n) time(it is a well-known problem).

Related

Comparison-based algorithm that pairs the largest element with the smallest one in linear time

Given an array of integers. I want to design a comparison-based algorithm
that pairs the largest element with the smallest one, the second largest one with the second smallest one and so on. Obviously, this is easy if I sort the array, but I want to do it in O(n) time. How can I possibly solve this problem?
Well i can prove that it does not exists.
Let`s proof by contradiction: suppose there was such algorithm
When we could get an array of kth min and kth max pairs.
We could when get sorted array by taking all mins in order then all max in order,
so we could get original array sorted in O(n) steps.
So we could get a comparision based sorting algorithm that sorts in O(n)
Yet it can be proven that comparision based sorting algorithm must take atleast n
log n steps. (many proofs online. i.e. https://www.geeksforgeeks.org/lower-bound-on-comparison-based-sorting-algorithms/)
Hence we have a contradiction so such algortihm does not
exist.

Constrained Longest Increasing Subsequence

Consider an array, which has N integers. Now we are given with an index i, which can take up values from 1 through N. This particular index should always be present in the LIS that we generate. Calculate the LIS for each value at i.
How can we solve the above problem efficiently? My straightforward solution is to vary the index i for all of its values and calculate LIS. The time complexity goes up to O(N2log(N)). Can it be beaten?
Example:
N = 2. i = 1
Say the given array is [1,2].
[1,2] or [2, 2]
The longest (strictly) increasing subsequence in each case is 2 and 1.
The canonical dynamic program for LIS computes, for each k, the longest increasing subsequence of the elements at index 1..k that includes the element at index k. Using this data and the mirror image data for longest increasing subsequences of k..n, we find the LIS that includes index k as the union of the longest before k and the longest after k.
O(n log n)
Having an index i that must be in the subsequence makes it an easy task to look to the left and right and see how far you can go to remain strictly increasing. This will take at most O(N) steps.
The straight forward solution will now just repeat this for all N values at the index i, which gives a total effort of O(N^2).
But note, that when changing the value at index i, the calculations done earlier can be reused. It is only necessary to check if the the sequence can be extended beyond i in either direction or not, If yes, you know already how far (or can calculate it now once and for all).
This brings the total effort down to O(N).

Longest Increasing Sub-sequence such that last-First element in LIS is maximum

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.

What is the best algorithm to find the longest double monotonically increasing sub-sequence of a sequence of n numbers?

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.

Minimal number of Increasing Subsequences

I have a sequence of integers {a1,a2...an} and I want to divide it into minimum number of "increasing subsequences". For example: let the sequence be {10,30,20,40}, then the answer would be 2. In this case, the first increasing sequence would be {10,30,40} and the second would be {20}. I am able to do it using an O(N^2) algorithm but I'm particularly interested in an O(N*logN) solution which could serve the purpose.
This could be done with simple greedy algorithm.
Keep sorted array of subsequences found so far. Sorted in decreasing order, by the value of the last integer in each sequence. Initially empty.
Get first not-yet-processed element from the sequence and find the subsequence where the last integer is smaller than this element but larger (or equal) than in all such subsequences. Use binary search here to get overall complexity O(N log N). If no such subsequence found, add a new one at the end of the array. Add this element to this subsequence. Repeat while there are not-yet-processed elements in the sequence.

Resources