Lis longest ascending subsequence n ^ 2 and nlogn Algorithm

Source: Internet
Author: User

This is a classic DP question, also known as lis (longest increasing subsequence. There are two basic algorithms for complexity: O (N * logn) and O (N ^ 2 ).

A.
O (N ^ 2) algorithm analysis is as follows:

(A [1]... A [n] stores all input values)
1. For a [n], because it is the last number, when searching from a [n], there is only a child sequence with a length of 1 and no descent;
2. If you start searching from a [n-1], there are two possibilities:
(1) If a [n-1] <A [n], there is a child sequence a [n-1], a [n] with a length of 2.
(2) If a [n-1]> A [n], there is a child sequence a [n-1] or a [n] with a length of 1.
3. Generally, if the subsequence starts from a [T], the maximum length of the subsequence is not decreased at this time, which should be obtained using the following method:
In a [t + 1], a [T + 2],... in a [n], find a child sequence that is larger than a [T] and is the longest and does not drop as its successor.
4. Define an array for algorithm needs:
Int d [N] [3];
D [T] [0] indicates a [T];
D [T] [1] indicates the maximum length of the subsequence that reaches N from position I;
D [T] [2] indicates the next position of the subsequence starting from position I.
The implementation code is as follows:
# Include <iostream>
Using namespace STD;
Int main ()
{
Int I, j, n, a [100], B [100], Max;
While (CIN> N)
{
For (I = 0; I <n; I ++)
Cin> A [I];
B [0] = 1; // initialization. the maximum length of the Child sequence ending with a [0] is 1.
For (I = 1; I <n; I ++)
{
B [I] = 1; // the minimum value of B [I] is 1.
For (j = 0; j <I; j ++)
If (A [I]> A [J] & B [J] + 1> B [I])
B [I] = B [J] + 1;
}
For (max = I = 0; I <n; I ++) // obtain the length of the longest ascending subsequence of the entire sequence
If (B [I]> MAX)
Max = B [I];
Cout <max <Endl;
}
Return 0;
}
Obviously, the time complexity of this method is still O (N ^ 2 );

B.
The analysis of the O (N * logn) algorithm of the longest sub-sequence without descent is as follows:

If a [T] indicates the number of T in the sequence, F [T] indicates the length of the longest ascending subsequence ending with T from 1 to T, set f [T] = 0 (T = 1, 2 ,..., len ()). Then there is a dynamic planning equation: F [T] = max {1, F [J] + 1} (j = 1, 2 ,..., t-1, and a [J] <A [T]).

Now, we carefully consider the situation when calculating f [T. Assume that two elements a [X] and a [y] Meet
(1) x <Y <t
(2) A [x] <A [y] <A [T]
(3) f [x] = f [y]
Select f [X] and select f [y] to obtain the same f [T] value. Then, in the position of the longest ascending subsequence, should I select a [x] or a [y?
Obviously, selecting a [x] is better than selecting a [Y. Because of the condition (2), in a [x + 1]... in the section A [T-1], if a [Z], a [x] <A [Z] <A [Y, A longer ascending subsequence is obtained.
Then, based on the condition (3), we will get an inspiration: classification based on the value of F. For each value K of F [], we only need to retain the minimum values of all a [T] that satisfy f [T] = K. Set d [k] to record this value, that is, d [k] = min {A [T]} (F [T] = K ).

Note the two features of d:
(1) The value of d [k] does not increase monotonically throughout the calculation process.
(2) The values of d [] are ordered, that is, d [1] <D [2] <D [3] <... <D [N].

Using d [], we can obtain another method to calculate the maximum length of the ascending subsequence. Set the maximum length of the obtained ascending subsequence to Len. First, judge a [T] And d [Len]. If a [T]> d [Len], a [T] is connected to d [Len] and a longer ascending subsequence is obtained. Len = Len + 1, d [Len] = A [T]; otherwise, in D [1] .. in D [Len], find the largest J, satisfying d [J] <A [T]. For k = J + 1, a [T] <= d [k] is generated. After a [T] is connected to d [J], a longer ascending subsequence is obtained, update d [k] = A [T]. Finally, Len is the maximum length of the ascending sub-sequence.

In the above algorithm, if you use the simple sequence to search for the data in the d [1] .. d [Len] search, because a total of O (n) elements need to be calculated, the complexity of each calculation is O (n ), the time complexity of the entire algorithm is O (n ^ 2), which is not improved compared with the original algorithm. However, due to the features of d [] (2), we can use binary lookup to efficiently complete the search in D, the time complexity of the entire algorithm is reduced to O (nlogn), which is greatly improved. Note that after the algorithm is completed, d [] does not record the longest ascending subsequence that matches the question!

# Include <iostream>
Using namespace STD;
Int find (int * a, int Len, int N) // if the return value is X, a [x]> = n> A [x-1]
{
Int left = 0, Right = Len, mid = (left + right)/2;
While (left <= right)
{
If (n> A [Mid]) Left = Mid + 1;
Else if (n <A [Mid]) Right = mid-1;
Else return mid;
Mid = (left + right)/2;
}
Return left;
}
Void fill (int * a, int N)
{
For (INT I = 0; I <= N; I ++)
A [I] = 1000;
}
Int main ()
{
Int Max, I, j, n, a [100], B [100], C [100];
While (CIN> N)
{
Fill (C, N + 1 );
For (I = 0; I <n; I ++)
Cin> A [I];
C [0] =-1 ;//................................................ 1
C [1] = A [0]; //…… 2
B [0] = 1 ;//................................................ 3
For (I = 1; I <n; I ++ )//.................................... 4
{
J = find (C, N + 1, a [I]); // ...... 5
C [J] = A [I]; //…… 6
B [I] = J ;//.......................................... 7
}
For (max = I = 0; I <n; I ++ )//.................................... 8
If (B [I]> MAX)
Max = B [I];
Cout <max <Endl;
}
Return 0;
}

For this program, we can use loop Invariants in the introduction to algorithms to help us understand it.
Loop Invariant: 1. c increases monotonically after each loop. (This property determines that binary search can be used)
2. After each loop, C [I] always saves the last element of the ascending sub-sequence with the length of I. If the length is the ascending sub-sequence of I

There are multiple columns and the smallest element at the end of the column is saved. (This property determines the premise that 3rd attributes are valid)
3. After each loop, B [I] always saves the longest ascending subsequence ending with a [I.
Initialization: 1. before entering the loop, C [0] =-1, C [1] = A [0], C's other elements are 1000, and C is monotonic increasing;
2. Before entering the loop, C [1] = A [0] saves the last element of the incremental sequence with a length of 1, and the length is 1

And C [1] is the smallest;
3. before entering the loop, B [0] = 1. At this time, the length of the longest incrementing subsequence ending with a [0] is 1.
Maintenance: 1. If C increases monotonically before the nth cycle, the value of C changes only in row 6th.

C is monotonically incrementing before entering the loop and the nature of the find function can be seen (see the comment of find ),

C [J + 1]> C [J]> = A [I]> C [J-1], so after the value of C [J] is updated to a [I, c [J + 1]> C [J]> C [J-1] is still

Stand, that is, C is still monotonically increasing;
2. in a loop, the value of C changes only in row 6th. After C [J]> = A [I] is updated to a [I, the value of C [J] only changes

Small values do not increase, because C [J] is the smallest value before entering the loop, C [J] is updated to a smaller a [I] in the loop. When

At this time, the value of C [J] is still the smallest;
3. In a loop, the value of B [I] Changes in row 7th, because of the nature of Loop Invariant 2, the return value of the find Function

For J has: C [J-1] <A [I] <= C [J], which indicates that C [J-1] is less than a [I, the ascending subsequence ending with C [J-1] has the largest

The length, that is, the J-1. After a [I] is connected to C [J-1], the longest incrementing subsequence ending with a [I] is obtained, and the length is (J-1) + 1 = J;
Termination: After the loop is complete, I = n-1, B [0], B [1],..., the values of B [n-1] have been obtained, that is, a [0], a [1],..., the longest delivery at the end of a [n-1]

The length of the incrementing sub-sequence has been obtained, and then the longest incrementing sub-sequence of the entire array is obtained through the cycle of 8th rows.

By carefully analyzing the code above, we can find that after each loop ends, assuming that C [1], C [2], C [3],..., c [Len] value, then the length of the longest incrementing sub-sequence is Len. Therefore, the code above can be simplified, that is, array B is not required for auxiliary storage, the cycle of the 8th rows can also be omitted.
# Include <iostream>
Using namespace STD;
Int find (int * a, int Len, int N) // binary search after modification. If the return value is X, a [x]> = N
{
Int left = 0, Right = Len, mid = (left + right)/2;
While (left <= right)
{
If (n> A [Mid]) Left = Mid + 1;
Else if (n <A [Mid]) Right = mid-1;
Else return mid;
Mid = (left + right)/2;
}
Return left;
}
Int main ()
{
Int n, a [100], C [100], I, j, Len; // a new variable Len, stores the maximum subscript of the element whose values have been obtained in C after each loop ends.
While (CIN> N)
{
For (I = 0; I <n; I ++)
Cin> A [I];
B [0] = 1;
C [0] =-1;
C [1] = A [0];
Len = 1; // at this time, only C [1] is obtained. The maximum length of the ascending subsequence is 1.
For (I = 1; I <n; I ++)
{
J = find (C, Len, a [I]);
C [J] = A [I];
If (j> Len) // update Len. Additionally, we can add that J is only 1 larger than Len in binary search.
Len = J; // update Len
}
Cout <Len <Endl;
}
Return 0;
}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.