I first saw this question in poj. I forgot the specific question, but the requiredAlgorithmIs consistent.
I was studying LCS, So I thought of a solution similar to LCS:
Use quick sorting for the original array, and then use the LCS idea to find the maximum public string. This solution is easy to understand, but the required space is: O (2n) = O (n); time is O (n ^ 2 + N * lgn) = O (N ^ 2), obviously this is not an optimal solution. But I did not think of a better solution ......
I recently saw the above questions about the beauty of programming, and then I was suddenly enlightened.
The book provides two solutions:
1. Based on the definition of No-aftereffect, you can use DP to solve the problem. According to the recursive formula: Lis [I + 1] = max {Lis [I + 1], lis [k] + 1} (when data [I + 1]> data [K], and K in [0, I]
After the above general term formula is obtained, you can simply writeCodeSolved. However, it should be noted that the current maximum value is constantly updated in the for loop to facilitate the function's final result return. This solution is a traditional DP, so the time complexity is O (n ^ 2) and the space complexity is O (n), but it is better than my solution in a progressive sense.
2. When considering the influence of the first I element on the I + 1 element, you can understand it as follows:When the maximum element of a subsequence is smaller than the current element, you can add the current element to the end of the sequence to form a new Lis.
Therefore, we need to find a lis of the first I element, and the maximum element of this LIS is smaller than array [I + 1], and the length is as long as possible.
To accelerate the implementation of the algorithm, an array with N length is constructed to maintain the maximum value of LIS with I length.
Therefore, the time complexity of this algorithm is O (n ^ 2), and the space complexity is O (2n) = O (n ).
The preceding algorithm is implemented as follows:
(Improvements to binary search are not implemented ......)
// The longest incrementing sub-sequence in the array <br/> # include <iostream> <br/> using namespace STD; <br/> template <class T> <br/> inline t maxintwoelement (const T & A, const T & B) <br/>{< br/> return A> B? A: B; <br/>}< br/> int slove1 (const int *, INT); // search by DP, O (N ^ 2 ), DP [I] = max {DP [J] + 1, DP [I]} (DP [I]> DP [J]) <br/> int slove2 (const int *, INT ); // use another array to save the minimum value of the largest element of LIS whose length is n <br/> int slove3 (const int *, INT); <br/> int DP [20]; <br/> void initialize () <br/> {<br/> memset (DP, 0, sizeof (DP); <br/> DP [0] = 1; <br/>}< br/> int main () <br/> {<br/> int (* P [3]) (const int *, INT) ={ & slove1, & slove2, & slove3}; <br/> int data [] = {1,-,-7}; <br/> for (INT I = 0; I <3; ++ I) <br/> {<br/> cout <p [I] (data, sizeof (data)/sizeof (INT) <Endl; <br/>}< br/> return 0; <br/>}< br/> int slove1 (const int * data, int length) <br/>{< br/> initialize (); <br/> int max = 1; <br/> for (INT I = 1; I <length; ++ I) <br/>{< br/> for (Int J = 0; j <I; ++ J) <br/> {<br/> If (data [I]> data [J]) <br/>{< br/> DP [I] = maxintwoelement (DP [J] + 1, DP [I]); <br />}< Br/> max = max> DP [I]? MAX: DP [I]; <br/>}< br/> return Max; <br/>}< br/> int slove2 (const int * data, int length) <br/> {<br/> int * maxele = new int [Length + 1]; <br/> maxele [0] =-int_max; <br/> maxele [1] = data [0]; <br/> // initialize <br/> for (INT I = 0; I <length; ++ I) <br/> DP [I] = 1; <br/> int maxlength = 1; <br/> for (INT I = 1; I <length; ++ I) // traversing the array <br/>{< br/> Int J; <br/> for (j = maxlength; j>-1; -- J) // find the max element int the LIS <br/>{< br/> If (data [I]> maxele [J]) // J is the length of sequence, too <br/> {// means it can be added to the sequence <br/> DP [I] = J + 1; <br/> break; <br/>}< br/> // now J = 0 or the index which firstly satisfied data [I]> maxele [J] <br/> If (DP [I]> maxlength) <br/> {// update the length and the element in maxele according to the length <br/> maxlength = DP [I]; <br/> maxele [DP [I] = data [I]; <br/>}< br/> else if (data [I]> maxele [J] & Data [I] <maxele [J + 1]) <br/> {// if the current value is not greater than the maximum length, update <br/> maxele [J + 1] = data [I]; <br/>}< br/> return maxlength; <br/>}< br/> int slove3 (const int * data, int length) <br/> {<br/> int * maxele = new int [Length + 1]; <br/> maxele [0] =-int_max; <br/> maxele [1] = data [0]; <br/> // initialize <br/> for (INT I = 0; I <length; ++ I) <br/> DP [I] = 1; <br/> int maxlength = 1; <br/> for (INT I = 1; I <length; ++ I) // traversing the array <br/>{< br/> Int J; <br/> // int BG = 0; <br/> // int end = maxlength; <br/> // here, cuz the maxele is ordered (can be proved), <br/> // we can use binary search <br/> // while (true) <br/> // {<br/> // J = (bg + end)/2; <br/> // If (data [I]> maxele [J]) <br/> // {<br/> // DP [I] = J + 1; <br/> // break; <br/> //} <br/> // else <br/> // {<br/> // end = J; <br/> //} <br/> for (j = maxlength; j> 0; -- J) // find the max element int the LIS <br/>{< br/> If (data [I]> maxele [J]) // J is the length of sequence, too <br/> {// means it can be added to the sequence <br/> DP [I] = J + 1; <br/> break; <br/>}< br/> // now J = 0 or the index which firstly satisfied data [I]> maxele [J] <br/> If (DP [I]> maxlength) <br/> {// update the length and the element in maxele according to the length <br/> maxlength = DP [I]; <br/> maxele [DP [I] = data [I]; <br/>}< br/> else if (data [I]> maxele [J] & Data [I] <maxele [J + 1]) <br/> {// if the current value is not greater than the maximum length, update <br/> maxele [J + 1] = data [I]; <br/>}< br/> return maxlength; <br/>}