In the previous article, we learned how to get the length of the longest incrementing sub-sequence of a one-dimensional array, but we do not know what this sub-sequence is! How can we list such a longest incrementing subsequence that meets the requirements?
In the second method described earlier, we used a MINV array, which is helpful for the subsequent implementation. We traverse from the first element of an array until the value in the LIS array corresponding to this element is not greater than the length of the longest incrementing subsequence. Let's assume that we use current to indicate the current element of the final longest incrementing sub-sequence to be obtained. If current is equal to 1, we will look for the first element in the sub-sequence. Add current to 1 after each query to find the next element. We also need to make some judgments on elements with the same Lis value. The following is an algorithm:
public static int lis2(int[] array){if(array==null||array.length==0)return -1;int len=array.length;int[] lis=new int[len];int maxlength=1;int[] minV=new int[len+2];minV[0]=minArray(array)-1;minV[1]=array[0];Arrays.fill(lis, 1);for(int i=1;i<len;i++){int j;for(j=maxlength;j>=0;j--){if(array[i]>minV[j]){lis[i]=j+1;break;}}if(lis[i]>maxlength){maxlength=lis[i];minV[lis[i]]=array[i];}else if(minV[j]<array[i]&&array[i]<minV[j+1]){minV[j+1]=array[i];}}minV[maxlength+1]=Integer.MAX_VALUE;System.out.println(Arrays.toString(lis));int current=1;for(int i=0;i<lis.length&¤t<=maxlength;i++){if(lis[i]==current){if(array[i]>minV[current+1])continue;System.out.print(array[i]+" ");current++;}}System.out.println();return maxlength;}
The running result is as follows:
1 2 4 5 7 length: 5 time: 285272 nanoseconds
If you have a better method, please advise.
The above provides a method for finding the longest recursive subsequence. We know that for an array, there may be multiple longest incrementing subsequences (these longest incrementing subsequences must have the same length). How can we obtain all the longest incrementing subsequences and list them all? I have thought of a method to share it with you. If you have any good method, please share it!
My idea is to use recursive methods. We compile a function that can search for the number of levels in a subsequence starting from a subscript, such as outputlis (INT level, int index, int [] Lis, int [] array, int [] MINV), where level indicates the number of digits in the subsequence we are looking for, index indicates the subscript from which to start searching, array is the original array, lis stores the possible position of the corresponding element in the final ascending subsequence. minv [I] stores the minimum value of the maximum element of the longest ascending subsequence with the length of I. Of course, we also need to use another array information in this method. This array is used to indicate whether an element in the original array is selected in the longest incrementing subsequence. The specific algorithm is given below:
// Output all the longest recursive subsequences Private Static void outputlis (INT level, int index, int [] Lis, int [] array, int [] MINV) {If (Level = maxlength + 1) {for (INT I = 0; I <flag. length; I ++) {If (flag [I]) {system. out. print (array [I] + "") ;}} system. out. println (); return;} while (LIS [Index]! = Level & index <array. length) index ++; while (index <array. length & Lis [Index] <LEVEL + 1) {If (LIS [Index] = level & array [Index] <MINV [Lis [Index] + 1]) {flag [Index] = true; outputlis (LEVEL + 1, index + 1, Lis, array, MINV); flag [Index] = false ;}index ++ ;}}
The running result is as follows:
1 2 4 5 7-1 2 4 5 7 length: 5: 422708 nanoseconds
Next, I will attach the complete program for your reference. Lis1 only calculates the length of the longest incrementing subsequence. lis2 calculates the length and lists a longest incrementing subsequence. lis3 calculates the length and returns all the longest incrementing subsequences.
Package COM. application. sample; import Java. util. arrays; import Java. util. iterator; import Java. util. stack; // obtain the longest incremental sub-sequence of a sequence public class lissample {Private Static Boolean [] flag; Private Static int maxlength; public static void main (string [] ARGs) {// todo auto-generated method stubint [] arr = {1,-6, 7}; long start = system. nanotime (); system. out. println ("Length:" + lis1 (ARR); long end = system. nanotime (); System. out. println ("time used:" + (end-Start) + "nanosecond"); Start = system. nanotime (); system. out. println ("Length:" + lis2 (ARR); End = system. nanotime (); system. out. println ("time used:" + (end-Start) + "nanosecond"); Start = system. nanotime (); system. out. println ("Length:" + lis3 (ARR); End = system. nanotime (); system. out. println ("time:" + (end-Start) + "nano");} public static int lis1 (INT [] array) {If (array = NULL | array. length = 0) Return-1; int Len = array. length; int [] Lis = new int [Len]; for (INT I = 0; I <Len; I ++) {Lis [I] = 1; for (Int J = 0; j <I; j ++) {If (array [J] <array [I] & (LIS [J] + 1)> Lis [I]) {Lis [I] = Lis [J] + 1 ;}} system. out. println (arrays. tostring (LIS); Return maxarray (LIS);} public static int lis2 (INT [] array) {If (array = NULL | array. length = 0) Return-1; int Len = array. length; int [] Lis = new int [Len]; int maxlength = 1; int [] MINV = new int [Len + 2]; MINV [0] = minarray (array) -1; MINV [1] = array [0]; arrays. fill (LIS, 1); For (INT I = 1; I <Len; I ++) {Int J; For (j = maxlength; j> = 0; j --) {If (array [I]> MINV [J]) {Lis [I] = J + 1; break;} If (LIS [I]> maxlength) {maxlength = Lis [I]; MINV [Lis [I] = array [I];} else if (MINV [J] <array [I] & array [I] <MINV [J + 1]) {MINV [J + 1] = array [I] ;}} MINV [maxlength + 1] = integer. max_value; system. out. println (arrays. tostring (LIS); int current = 1; for (INT I = 0; I <Lis. length & lt; = maxlength; I ++) {If (LIS [I] = current) {If (array [I]> MINV [current + 1]) continue; system. out. print (array [I] + ""); current ++;} system. out. println (); Return maxlength;} public static int lis3 (INT [] array) {If (array = NULL | array. length = 0) Return-1; int Len = array. length; flag = new Boolean [Len]; int [] Lis = new int [Len]; int maxlength = 1; int [] MINV = new int [Len + 2]; MINV [0] = integer. min_value; MINV [1] = array [0]; arrays. fill (LIS, 1); // For (INT I = 1; I <Len; I ++) // {// in T j; // For (j = Lis [I-1]; j> 0; j --) // {// If (array [I]> MINV [J]) // {// Lis [I] = J + 1; // break; //} // If (LIS [I]> maxlength) /// {// maxlength = Lis [I]; // MINV [Lis [I] = array [I]; //} else if (MINV [J] <array [I] & array [I] <MINV [J + 1]) // {// MINV [J + 1] = array [I]; //} For (INT I = 1; I <Len; I ++) {Int J; For (j = maxlength; j> = 0; j --) {If (array [I]> MINV [J]) {Lis [I] = J + 1; break;} If (LIS [I]> maxlength) {maxlength = Lis [I]; MINV [Lis [I] = array [I];} else if (MINV [J] <Array [I] & array [I] <MINV [J + 1]) {MINV [J + 1] = array [I] ;}} system. out. println (arrays. tostring (LIS); MINV [maxlength + 1] = integer. max_value; system. out. println (arrays. tostring (MINV); lissample. maxlength = maxlength; outputlis (, Lis, array, MINV); Return maxlength;} // output all the longest recursive subsequences Private Static void outputlis (INT level, int index, int [] Lis, int [] array, int [] MINV) {If (Level = maxlength + 1) {for (INT I = 0; I <flag. length; I ++) {If (flag [I]) {system. out. print (array [I] + "") ;}} system. out. println (); return;} while (LIS [Index]! = Level & index <array. length) index ++; while (index <array. length & Lis [Index] <LEVEL + 1) {If (LIS [Index] = level & array [Index] <MINV [Lis [Index] + 1]) {flag [Index] = true; outputlis (LEVEL + 1, index + 1, Lis, array, MINV); flag [Index] = false ;}index ++ ;}} private Static int minarray (INT [] array) {int result = array [0]; for (INT I = 1; I <array. length; I ++) {If (array [I] <result) Result = array [I];} return result;} Private Static int maxarray (INT [] array) {int result = array [0]; for (INT I = 1; I <array. length; I ++) {If (array [I]> result) Result = array [I];} return result ;}}
The overall running result is as follows:
[1, 1, 2, 1, 3, 1, 4, 1, 5] duration: 5: 360476 nanoseconds [1, 1, 2, 1, 3, 1, 4, 1, 5] 1 2 4 5 7 length: 5: 433169 nanoseconds [1, 1, 2, 1, 3, 1, 4, 1, 1, 5] [-2147483648,-6, 2, 4, 5, 7, 2147483647, 0, 0, 0, 0] 1 2 4 5 7-1 2 4 5 7 length: 5: 451083 nanoseconds
Thank you for your comments and good methods! Indicate the source for reprinting.